From 3af1b1f5b61fcb3fdbd215ce2b5e5f8fcc151ce0 Mon Sep 17 00:00:00 2001 From: Sen Date: Sun, 16 Mar 2025 17:40:47 +0100 Subject: [PATCH] use latest Netty and Guava --- java/src/game/Game.java | 11 +- java/src/game/Server.java | 45 +- java/src/game/Temp1.java | 18 +- java/src/game/ai/EntityAIAvoidEntity.java | 7 +- java/src/game/ai/EntityAIEatGrass.java | 8 +- .../game/ai/EntityAIFindEntityNearest.java | 4 +- .../game/ai/EntityAIMoveThroughVillage.java | 3 +- .../ai/EntityAINearestAttackableTarget.java | 6 +- java/src/game/ai/EntityAITakePlace.java | 3 +- java/src/game/ai/EntityAITargetNonTamed.java | 2 +- java/src/game/ai/EntityAITasks.java | 2 +- java/src/game/ai/EntitySenses.java | 3 +- java/src/game/audio/AudioInterface.java | 4 +- java/src/game/audio/SoundManager.java | 9 +- java/src/game/biome/Biome.java | 5 +- java/src/game/block/Block.java | 15 +- java/src/game/block/BlockButton.java | 3 +- java/src/game/block/BlockDoor.java | 3 +- java/src/game/block/BlockFence.java | 3 +- java/src/game/block/BlockFire.java | 3 +- java/src/game/block/BlockFloorPortal.java | 3 +- java/src/game/block/BlockFlower.java | 13 +- java/src/game/block/BlockHopper.java | 4 +- java/src/game/block/BlockLeaves.java | 3 +- java/src/game/block/BlockPistonBase.java | 3 +- java/src/game/block/BlockRailBase.java | 3 +- java/src/game/block/BlockRailDetector.java | 7 +- java/src/game/block/BlockRailPowered.java | 4 +- .../game/block/BlockRedstoneComparator.java | 2 +- java/src/game/block/BlockRedstoneTorch.java | 5 +- java/src/game/block/BlockRedstoneWire.java | 5 +- java/src/game/block/BlockSapling.java | 3 +- java/src/game/block/BlockSlab.java | 3 +- java/src/game/block/BlockStem.java | 4 +- java/src/game/block/BlockTorch.java | 4 +- java/src/game/clipboard/ClipboardPlacer.java | 3 +- java/src/game/clipboard/Rotation.java | 4 +- java/src/game/collect/AbstractBiMap.java | 399 -- .../collect/AbstractIndexedListIterator.java | 106 - java/src/game/collect/AbstractIterator.java | 173 - java/src/game/collect/AbstractMapEntry.java | 62 - java/src/game/collect/AbstractTable.java | 223 - java/src/game/collect/BiMap.java | 106 - .../game/collect/CollectPreconditions.java | 49 - .../src/game/collect/DenseImmutableTable.java | 273 -- java/src/game/collect/EmptyImmutableMap.java | 304 -- java/src/game/collect/EmptyImmutableSet.java | 93 - java/src/game/collect/Filter.java | 659 --- .../game/collect/ForwardingCollection.java | 250 -- java/src/game/collect/ForwardingMap.java | 302 -- java/src/game/collect/ForwardingMapEntry.java | 122 - java/src/game/collect/ForwardingObject.java | 72 - java/src/game/collect/ForwardingSet.java | 96 - java/src/game/collect/HashBiMap.java | 658 --- java/src/game/collect/Hashing.java | 67 - java/src/game/collect/ImmutableAsList.java | 81 - .../src/game/collect/ImmutableCollection.java | 360 -- java/src/game/collect/ImmutableEntry.java | 48 - java/src/game/collect/ImmutableEnumMap.java | 146 - java/src/game/collect/ImmutableEnumSet.java | 117 - java/src/game/collect/ImmutableList.java | 743 ---- java/src/game/collect/ImmutableMap.java | 548 --- java/src/game/collect/ImmutableMapEntry.java | 68 - .../game/collect/ImmutableMapEntrySet.java | 71 - java/src/game/collect/ImmutableMapKeySet.java | 90 - java/src/game/collect/ImmutableMapValues.java | 88 - java/src/game/collect/ImmutableSet.java | 533 --- java/src/game/collect/ImmutableTable.java | 436 -- java/src/game/collect/Iterables.java | 1029 ----- java/src/game/collect/Iterators.java | 1296 ------ java/src/game/collect/Lists.java | 49 - java/src/game/collect/Maps.java | 3953 ----------------- java/src/game/collect/ObjectArrays.java | 244 - java/src/game/collect/Preconditions.java | 350 -- .../game/collect/RegularImmutableAsList.java | 65 - .../game/collect/RegularImmutableList.java | 106 - .../src/game/collect/RegularImmutableMap.java | 205 - .../src/game/collect/RegularImmutableSet.java | 92 - .../game/collect/RegularImmutableTable.java | 175 - java/src/game/collect/Sets.java | 1607 ------- .../game/collect/SparseImmutableTable.java | 108 - java/src/game/collect/StandardTable.java | 891 ---- java/src/game/collect/Table.java | 291 -- .../src/game/collect/TransformedIterator.java | 53 - .../game/collect/UnmodifiableIterator.java | 43 - .../collect/UnmodifiableListIterator.java | 53 - java/src/game/color/DyeColor.java | 3 +- java/src/game/command/ArgumentParser.java | 2 +- java/src/game/command/CachedExecutable.java | 4 +- java/src/game/command/EnumParser.java | 2 +- java/src/game/command/ScriptArgs.java | 3 +- java/src/game/command/ScriptEnvironment.java | 5 +- java/src/game/command/ScriptExecutable.java | 4 +- java/src/game/command/StringParser.java | 2 +- java/src/game/command/WorldParser.java | 3 +- java/src/game/dimension/DimType.java | 2 +- java/src/game/dimension/Dimension.java | 7 +- java/src/game/dimension/Domain.java | 2 +- java/src/game/dimension/Galaxy.java | 2 +- java/src/game/dimension/Planet.java | 2 +- java/src/game/dimension/Sector.java | 2 +- java/src/game/dimension/Star.java | 3 +- java/src/game/enchantment/Enchantment.java | 5 +- .../game/enchantment/EnchantmentHelper.java | 5 +- java/src/game/entity/DataWatcher.java | 5 +- java/src/game/entity/EntityTrackerEntry.java | 3 +- java/src/game/entity/animal/EntityDragon.java | 3 +- java/src/game/entity/animal/EntityHorse.java | 4 +- java/src/game/entity/animal/EntityOcelot.java | 4 +- java/src/game/entity/animal/EntityRabbit.java | 4 +- java/src/game/entity/animal/EntitySheep.java | 3 +- java/src/game/entity/animal/EntityWolf.java | 4 +- .../src/game/entity/attributes/Attribute.java | 3 +- .../entity/attributes/AttributeInstance.java | 6 +- .../game/entity/attributes/AttributeMap.java | 7 +- .../entity/attributes/LowerStringMap.java | 2 +- java/src/game/entity/item/EntityFalling.java | 3 +- .../game/entity/item/EntityHopperCart.java | 4 +- java/src/game/entity/npc/Alignment.java | 3 +- java/src/game/entity/npc/ClassInfo.java | 3 +- .../game/entity/npc/EntityChaosMarine.java | 3 +- java/src/game/entity/npc/EntityNPC.java | 9 +- java/src/game/entity/npc/EntityPrimarch.java | 3 +- .../game/entity/npc/EntitySpaceMarine.java | 3 +- java/src/game/entity/npc/EntityZombie.java | 4 +- java/src/game/entity/npc/SpeciesInfo.java | 9 +- java/src/game/entity/types/EntityAnimal.java | 3 +- java/src/game/entity/types/EntityLiving.java | 9 +- java/src/game/future/AbstractFuture.java | 392 -- java/src/game/future/ExecutionError.java | 60 - java/src/game/future/ExecutionList.java | 170 - java/src/game/future/FutureCallback.java | 43 - java/src/game/future/Futures.java | 1723 ------- java/src/game/future/ListenableFuture.java | 132 - .../src/game/future/ListenableFutureTask.java | 91 - java/src/game/future/MoreExecutors.java | 889 ---- .../src/game/future/ThreadFactoryBuilder.java | 176 - .../future/UncheckedExecutionException.java | 65 - java/src/game/gui/Gui.java | 3 +- java/src/game/gui/GuiConsole.java | 3 +- java/src/game/gui/GuiInfo.java | 4 +- java/src/game/gui/container/GuiContainer.java | 5 +- java/src/game/gui/element/GuiList.java | 3 +- java/src/game/gui/world/GuiWorlds.java | 3 +- java/src/game/init/CraftingRegistry.java | 5 +- java/src/game/init/EntityRegistry.java | 3 +- java/src/game/init/FluidRegistry.java | 5 +- java/src/game/init/ItemRegistry.java | 5 +- java/src/game/init/ObjectIntIdentityMap.java | 6 +- java/src/game/init/RegistryNamespaced.java | 4 +- java/src/game/init/RegistrySimple.java | 2 +- java/src/game/init/RotationRegistry.java | 9 +- java/src/game/init/SmeltingRegistry.java | 4 +- java/src/game/init/SpeciesRegistry.java | 7 +- java/src/game/init/TileRegistry.java | 3 +- java/src/game/init/ToolMaterial.java | 3 +- java/src/game/init/UniverseRegistry.java | 8 +- java/src/game/inventory/Container.java | 5 +- .../game/inventory/ContainerLocalMenu.java | 3 +- java/src/game/inventory/ContainerPlayer.java | 3 +- java/src/game/inventory/InventoryBasic.java | 3 +- java/src/game/item/Item.java | 5 +- java/src/game/item/ItemArmor.java | 7 +- java/src/game/item/ItemBucket.java | 3 +- java/src/game/item/ItemBucketMilk.java | 3 +- java/src/game/item/ItemFirework.java | 3 +- java/src/game/item/ItemFishFood.java | 3 +- java/src/game/item/ItemMagnet.java | 4 +- java/src/game/item/ItemMetal.java | 3 +- java/src/game/item/ItemMetalBlock.java | 3 +- java/src/game/item/ItemPotion.java | 6 +- java/src/game/item/ItemStack.java | 6 +- java/src/game/item/ItemSword.java | 3 +- java/src/game/item/ItemTool.java | 3 +- java/src/game/log/Log.java | 3 +- java/src/game/model/BakedModel.java | 3 +- java/src/game/model/ModelBakery.java | 8 +- java/src/game/model/ModelManager.java | 4 +- java/src/game/model/ModelRotation.java | 3 +- java/src/game/nbt/NBTParser.java | 2 +- java/src/game/nbt/NBTTagCompound.java | 5 +- java/src/game/nbt/NBTTagList.java | 3 +- .../game/net/bootstrap/AbstractBootstrap.java | 474 -- java/src/game/net/bootstrap/Bootstrap.java | 233 - .../game/net/bootstrap/ChannelFactory.java | 29 - .../game/net/bootstrap/ServerBootstrap.java | 332 -- java/src/game/net/buffer/AbstractByteBuf.java | 1190 ----- .../net/buffer/AbstractByteBufAllocator.java | 219 - .../net/buffer/AbstractDerivedByteBuf.java | 67 - .../AbstractReferenceCountedByteBuf.java | 140 - .../net/buffer/AdvancedLeakAwareByteBuf.java | 724 --- java/src/game/net/buffer/ByteBuf.java | 1879 -------- .../src/game/net/buffer/ByteBufAllocator.java | 128 - .../game/net/buffer/ByteBufInputStream.java | 257 -- .../game/net/buffer/ByteBufOutputStream.java | 146 - .../src/game/net/buffer/ByteBufProcessor.java | 126 - java/src/game/net/buffer/ByteBufUtil.java | 483 -- .../src/game/net/buffer/CompositeByteBuf.java | 1602 ------- .../game/net/buffer/DuplicatedByteBuf.java | 305 -- java/src/game/net/buffer/EmptyByteBuf.java | 870 ---- java/src/game/net/buffer/PoolArena.java | 477 -- java/src/game/net/buffer/PoolChunk.java | 431 -- java/src/game/net/buffer/PoolChunkList.java | 129 - java/src/game/net/buffer/PoolSubpage.java | 213 - java/src/game/net/buffer/PoolThreadCache.java | 485 -- java/src/game/net/buffer/PooledByteBuf.java | 160 - .../net/buffer/PooledByteBufAllocator.java | 334 -- .../game/net/buffer/PooledDirectByteBuf.java | 377 -- .../game/net/buffer/PooledHeapByteBuf.java | 307 -- .../net/buffer/PooledUnsafeDirectByteBuf.java | 394 -- java/src/game/net/buffer/ReadOnlyByteBuf.java | 317 -- .../net/buffer/ReadOnlyByteBufferBuf.java | 335 -- .../buffer/ReadOnlyUnsafeDirectByteBuf.java | 138 - .../net/buffer/SimpleLeakAwareByteBuf.java | 79 - java/src/game/net/buffer/SlicedByteBuf.java | 296 -- java/src/game/net/buffer/SwappedByteBuf.java | 852 ---- java/src/game/net/buffer/Unpooled.java | 861 ---- .../net/buffer/UnpooledByteBufAllocator.java | 62 - .../net/buffer/UnpooledDirectByteBuf.java | 604 --- .../game/net/buffer/UnpooledHeapByteBuf.java | 449 -- .../buffer/UnpooledUnsafeDirectByteBuf.java | 524 --- .../game/net/buffer/UnreleasableByteBuf.java | 87 - .../buffer/UnsafeDirectSwappedByteBuf.java | 186 - java/src/game/net/buffer/WrappedByteBuf.java | 827 ---- .../src/game/net/channel/AbstractChannel.java | 873 ---- .../AbstractChannelHandlerContext.java | 1000 ----- .../net/channel/AbstractServerChannel.java | 83 - .../channel/AdaptiveRecvByteBufAllocator.java | 182 - java/src/game/net/channel/Channel.java | 511 --- java/src/game/net/channel/ChannelConfig.java | 249 -- .../game/net/channel/ChannelException.java | 51 - java/src/game/net/channel/ChannelFuture.java | 192 - .../net/channel/ChannelFutureListener.java | 74 - java/src/game/net/channel/ChannelHandler.java | 211 - .../net/channel/ChannelHandlerAdapter.java | 80 - .../net/channel/ChannelHandlerContext.java | 489 -- .../net/channel/ChannelInboundHandler.java | 74 - .../channel/ChannelInboundHandlerAdapter.java | 133 - .../game/net/channel/ChannelInitializer.java | 82 - .../src/game/net/channel/ChannelMetadata.java | 44 - java/src/game/net/channel/ChannelOption.java | 111 - .../net/channel/ChannelOutboundBuffer.java | 650 --- .../net/channel/ChannelOutboundHandler.java | 99 - .../ChannelOutboundHandlerAdapter.java | 117 - .../src/game/net/channel/ChannelPipeline.java | 872 ---- .../net/channel/ChannelPipelineException.java | 52 - .../channel/ChannelProgressivePromise.java | 86 - java/src/game/net/channel/ChannelPromise.java | 63 - .../net/channel/CompleteChannelFuture.java | 107 - .../net/channel/ConnectTimeoutException.java | 33 - .../net/channel/DefaultChannelConfig.java | 355 -- .../channel/DefaultChannelHandlerContext.java | 45 - .../net/channel/DefaultChannelPipeline.java | 1067 ----- .../net/channel/DefaultChannelPromise.java | 159 - .../channel/DefaultMessageSizeEstimator.java | 71 - java/src/game/net/channel/EventLoop.java | 30 - .../game/net/channel/EventLoopException.java | 41 - java/src/game/net/channel/EventLoopGroup.java | 43 - .../game/net/channel/FailedChannelFuture.java | 65 - .../net/channel/MessageSizeEstimator.java | 39 - .../channel/MultithreadEventLoopGroup.java | 71 - .../net/channel/RecvByteBufAllocator.java | 54 - java/src/game/net/channel/ServerChannel.java | 25 - .../channel/SimpleChannelInboundHandler.java | 129 - .../net/channel/SingleThreadEventLoop.java | 72 - .../net/channel/SucceededChannelFuture.java | 45 - .../game/net/channel/VoidChannelPromise.java | 205 - .../game/net/channel/local/LocalAddress.java | 94 - .../game/net/channel/local/LocalChannel.java | 383 -- .../channel/local/LocalChannelRegistry.java | 62 - .../net/channel/local/LocalEventLoop.java | 42 - .../channel/local/LocalEventLoopGroup.java | 59 - .../net/channel/local/LocalServerChannel.java | 164 - .../channel/nio/AbstractNioByteChannel.java | 347 -- .../net/channel/nio/AbstractNioChannel.java | 460 -- .../nio/AbstractNioMessageChannel.java | 187 - .../game/net/channel/nio/NioEventLoop.java | 691 --- .../net/channel/nio/NioEventLoopGroup.java | 87 - java/src/game/net/channel/nio/NioTask.java | 40 - .../channel/nio/SelectedSelectionKeySet.java | 110 - .../socket/ChannelInputShutdownEvent.java | 33 - .../DefaultServerSocketChannelConfig.java | 203 - .../socket/DefaultSocketChannelConfig.java | 348 -- .../channel/socket/ServerSocketChannel.java | 32 - .../socket/ServerSocketChannelConfig.java | 104 - .../net/channel/socket/SocketChannel.java | 61 - .../channel/socket/SocketChannelConfig.java | 177 - .../socket/nio/NioServerSocketChannel.java | 197 - .../channel/socket/nio/NioSocketChannel.java | 320 -- .../handler/codec/ByteToMessageDecoder.java | 306 -- .../net/handler/codec/CodecException.java | 51 - .../codec/CorruptedFrameException.java | 52 - .../net/handler/codec/DecoderException.java | 51 - .../net/handler/codec/EncoderException.java | 51 - .../handler/codec/MessageToByteEncoder.java | 154 - .../handler/timeout/ReadTimeoutException.java | 29 - .../handler/timeout/ReadTimeoutHandler.java | 218 - .../net/handler/timeout/TimeoutException.java | 34 - java/src/game/net/util/Attribute.java | 67 - java/src/game/net/util/AttributeKey.java | 49 - java/src/game/net/util/AttributeMap.java | 29 - java/src/game/net/util/CharsetUtil.java | 117 - .../game/net/util/DefaultAttributeMap.java | 179 - .../util/IllegalReferenceCountException.java | 48 - java/src/game/net/util/NetUtil.java | 614 --- java/src/game/net/util/Recycler.java | 353 -- .../src/game/net/util/ReferenceCountUtil.java | 161 - java/src/game/net/util/ReferenceCounted.java | 63 - java/src/game/net/util/ResourceLeak.java | 32 - .../game/net/util/ResourceLeakDetector.java | 388 -- java/src/game/net/util/Signal.java | 77 - .../src/game/net/util/ThreadDeathWatcher.java | 241 - java/src/game/net/util/UniqueName.java | 117 - .../concurrent/AbstractEventExecutor.java | 157 - .../AbstractEventExecutorGroup.java | 116 - .../net/util/concurrent/AbstractFuture.java | 51 - .../BlockingOperationException.java | 41 - .../net/util/concurrent/CompleteFuture.java | 147 - .../util/concurrent/DefaultEventExecutor.java | 45 - .../concurrent/DefaultEventExecutorGroup.java | 48 - .../concurrent/DefaultFutureListeners.java | 86 - .../concurrent/DefaultProgressivePromise.java | 130 - .../net/util/concurrent/DefaultPromise.java | 876 ---- .../util/concurrent/DefaultThreadFactory.java | 143 - .../net/util/concurrent/EventExecutor.java | 72 - .../util/concurrent/EventExecutorGroup.java | 112 - .../net/util/concurrent/FailedFuture.java | 69 - .../net/util/concurrent/FastThreadLocal.java | 244 - .../concurrent/FastThreadLocalThread.java | 72 - java/src/game/net/util/concurrent/Future.java | 168 - .../net/util/concurrent/FutureListener.java | 28 - .../concurrent/GenericFutureListener.java | 32 - .../GenericProgressiveFutureListener.java | 28 - .../util/concurrent/GlobalEventExecutor.java | 391 -- .../concurrent/ImmediateEventExecutor.java | 121 - .../util/concurrent/ImmediateExecutor.java | 37 - .../MultithreadEventExecutorGroup.java | 233 - .../util/concurrent/ProgressiveFuture.java | 47 - .../util/concurrent/ProgressivePromise.java | 65 - .../src/game/net/util/concurrent/Promise.java | 90 - .../game/net/util/concurrent/PromiseTask.java | 137 - .../net/util/concurrent/ScheduledFuture.java | 23 - .../util/concurrent/ScheduledFutureTask.java | 161 - .../concurrent/SingleThreadEventExecutor.java | 870 ---- .../net/util/concurrent/SucceededFuture.java | 50 - java/src/game/net/util/internal/Cleaner0.java | 74 - .../game/net/util/internal/EmptyArrays.java | 39 - .../game/net/util/internal/IntegerHolder.java | 21 - .../util/internal/InternalThreadLocalMap.java | 309 -- .../net/util/internal/MpscLinkedQueue.java | 397 -- .../util/internal/MpscLinkedQueueHeadRef.java | 54 - .../util/internal/MpscLinkedQueueNode.java | 65 - .../util/internal/MpscLinkedQueuePad0.java | 22 - .../util/internal/MpscLinkedQueuePad1.java | 25 - .../util/internal/MpscLinkedQueueTailRef.java | 54 - .../internal/NoOpTypeParameterMatcher.java | 24 - .../game/net/util/internal/OneTimeTask.java | 30 - .../net/util/internal/PlatformDependent.java | 844 ---- .../net/util/internal/PlatformDependent0.java | 383 -- .../util/internal/RecyclableArrayList.java | 132 - .../RecyclableMpscLinkedQueueNode.java | 45 - .../game/net/util/internal/StringUtil.java | 274 -- .../net/util/internal/SystemPropertyUtil.java | 223 - .../net/util/internal/ThreadLocalRandom.java | 336 -- .../util/internal/TypeParameterMatcher.java | 177 - .../UnpaddedInternalThreadLocalMap.java | 55 - .../UnsafeAtomicIntegerFieldUpdater.java | 61 - .../UnsafeAtomicLongFieldUpdater.java | 61 - .../UnsafeAtomicReferenceFieldUpdater.java | 62 - .../logging/AbstractInternalLogger.java | 190 - .../internal/logging/FormattingTuple.java | 88 - .../internal/logging/InternalLogLevel.java | 42 - .../util/internal/logging/InternalLogger.java | 444 -- .../logging/InternalLoggerFactory.java | 91 - .../net/util/internal/logging/JdkLogger.java | 647 --- .../internal/logging/JdkLoggerFactory.java | 32 - .../internal/logging/MessageFormatter.java | 427 -- java/src/game/network/IThreadListener.java | 2 +- java/src/game/network/NetConnection.java | 47 +- .../game/network/NetHandlerPlayClient.java | 4 +- .../game/network/NetHandlerPlayServer.java | 13 +- .../game/network/NettyCompressionDecoder.java | 10 +- .../game/network/NettyCompressionEncoder.java | 6 +- java/src/game/network/PacketBuffer.java | 14 +- java/src/game/network/PacketDecoder.java | 6 +- java/src/game/network/PacketEncoder.java | 6 +- java/src/game/network/PacketPrepender.java | 6 +- java/src/game/network/PacketRegistry.java | 7 +- java/src/game/network/PacketSplitter.java | 10 +- .../packet/S20PacketEntityProperties.java | 3 +- java/src/game/packet/S27PacketExplosion.java | 3 +- .../game/packet/S38PacketPlayerListItem.java | 3 +- java/src/game/packet/SPacketChunkData.java | 3 +- java/src/game/pattern/BlockStateHelper.java | 9 +- java/src/game/potion/Potion.java | 4 +- java/src/game/potion/PotionHelper.java | 4 +- java/src/game/properties/PropertyBool.java | 2 +- .../game/properties/PropertyDirection.java | 11 +- java/src/game/properties/PropertyEnum.java | 14 +- java/src/game/properties/PropertyInteger.java | 4 +- java/src/game/renderer/BlockRenderer.java | 3 +- java/src/game/renderer/EntityRenderer.java | 4 +- java/src/game/renderer/ItemModelMesher.java | 5 +- java/src/game/renderer/RenderGlobal.java | 7 +- java/src/game/renderer/VertexFormat.java | 3 +- .../game/renderer/blockmodel/ModelBlock.java | 5 +- .../renderer/blockmodel/ModelGenerator.java | 5 +- .../renderer/blockmodel/MultiStateMap.java | 5 +- .../game/renderer/blockmodel/StateMap.java | 3 +- .../chunk/ChunkCompileTaskGenerator.java | 3 +- .../renderer/chunk/ChunkRenderDispatcher.java | 11 +- .../renderer/chunk/ChunkRenderWorker.java | 12 +- .../game/renderer/chunk/CompiledChunk.java | 3 +- java/src/game/renderer/chunk/RenderChunk.java | 5 +- .../src/game/renderer/entity/RenderHorse.java | 3 +- .../game/renderer/entity/RenderManager.java | 3 +- .../renderer/entity/RendererLivingEntity.java | 3 +- java/src/game/renderer/layers/LayerExtra.java | 3 +- java/src/game/renderer/model/ModelBase.java | 5 +- .../game/renderer/model/ModelRenderer.java | 3 +- .../renderer/particle/EffectRenderer.java | 5 +- .../game/renderer/particle/ParticleType.java | 4 +- .../renderer/texture/EntityTexManager.java | 8 +- .../game/renderer/texture/LayeredTexture.java | 3 +- java/src/game/renderer/texture/Stitcher.java | 4 +- .../renderer/texture/TextureAtlasSprite.java | 2 +- .../game/renderer/texture/TextureManager.java | 3 +- .../src/game/renderer/texture/TextureMap.java | 5 +- .../tileentity/TileEntityBannerRenderer.java | 5 +- .../TileEntityRendererDispatcher.java | 3 +- java/src/game/rng/WeightedList.java | 2 +- .../src/game/tileentity/TileEntityBanner.java | 3 +- .../src/game/tileentity/TileEntityHopper.java | 6 +- .../src/game/tileentity/TileEntityPiston.java | 3 +- java/src/game/util/FileUtils.java | 2 +- java/src/game/util/Predicates.java | 645 --- java/src/game/village/Village.java | 3 +- java/src/game/village/VillageCollection.java | 3 +- java/src/game/world/BlockPos.java | 3 +- java/src/game/world/Chunk.java | 11 +- .../game/world/ClassInheritanceMultiMap.java | 10 +- java/src/game/world/Converter.java | 3 +- java/src/game/world/EmptyChunk.java | 2 +- java/src/game/world/Explosion.java | 7 +- java/src/game/world/Facing.java | 11 +- java/src/game/world/Region.java | 5 +- java/src/game/world/Spawner.java | 3 +- java/src/game/world/State.java | 17 +- java/src/game/world/Weather.java | 3 +- java/src/game/world/World.java | 9 +- java/src/game/world/WorldClient.java | 5 +- java/src/game/world/WorldServer.java | 11 +- java/src/game/worldgen/BiomeGenLayered.java | 3 +- java/src/game/worldgen/GeneratorDebug.java | 3 +- .../worldgen/feature/WorldGenDesertWells.java | 5 +- java/src/game/worldgen/layer/IntCache.java | 2 +- .../worldgen/structure/MapGenStructure.java | 3 +- .../worldgen/structure/MapGenStructureIO.java | 3 +- .../worldgen/structure/MapGenVillage.java | 3 +- .../worldgen/structure/StructureBridge.java | 3 +- .../structure/StructureStronghold.java | 5 +- .../worldgen/structure/StructureVillage.java | 3 +- .../game/worldgen/tree/WorldGenBigTree.java | 3 +- 463 files changed, 611 insertions(+), 68249 deletions(-) delete mode 100644 java/src/game/collect/AbstractBiMap.java delete mode 100644 java/src/game/collect/AbstractIndexedListIterator.java delete mode 100644 java/src/game/collect/AbstractIterator.java delete mode 100644 java/src/game/collect/AbstractMapEntry.java delete mode 100644 java/src/game/collect/AbstractTable.java delete mode 100644 java/src/game/collect/BiMap.java delete mode 100644 java/src/game/collect/CollectPreconditions.java delete mode 100644 java/src/game/collect/DenseImmutableTable.java delete mode 100644 java/src/game/collect/EmptyImmutableMap.java delete mode 100644 java/src/game/collect/EmptyImmutableSet.java delete mode 100644 java/src/game/collect/Filter.java delete mode 100644 java/src/game/collect/ForwardingCollection.java delete mode 100644 java/src/game/collect/ForwardingMap.java delete mode 100644 java/src/game/collect/ForwardingMapEntry.java delete mode 100644 java/src/game/collect/ForwardingObject.java delete mode 100644 java/src/game/collect/ForwardingSet.java delete mode 100644 java/src/game/collect/HashBiMap.java delete mode 100644 java/src/game/collect/Hashing.java delete mode 100644 java/src/game/collect/ImmutableAsList.java delete mode 100644 java/src/game/collect/ImmutableCollection.java delete mode 100644 java/src/game/collect/ImmutableEntry.java delete mode 100644 java/src/game/collect/ImmutableEnumMap.java delete mode 100644 java/src/game/collect/ImmutableEnumSet.java delete mode 100644 java/src/game/collect/ImmutableList.java delete mode 100644 java/src/game/collect/ImmutableMap.java delete mode 100644 java/src/game/collect/ImmutableMapEntry.java delete mode 100644 java/src/game/collect/ImmutableMapEntrySet.java delete mode 100644 java/src/game/collect/ImmutableMapKeySet.java delete mode 100644 java/src/game/collect/ImmutableMapValues.java delete mode 100644 java/src/game/collect/ImmutableSet.java delete mode 100644 java/src/game/collect/ImmutableTable.java delete mode 100644 java/src/game/collect/Iterables.java delete mode 100644 java/src/game/collect/Iterators.java delete mode 100644 java/src/game/collect/Lists.java delete mode 100644 java/src/game/collect/Maps.java delete mode 100644 java/src/game/collect/ObjectArrays.java delete mode 100644 java/src/game/collect/Preconditions.java delete mode 100644 java/src/game/collect/RegularImmutableAsList.java delete mode 100644 java/src/game/collect/RegularImmutableList.java delete mode 100644 java/src/game/collect/RegularImmutableMap.java delete mode 100644 java/src/game/collect/RegularImmutableSet.java delete mode 100644 java/src/game/collect/RegularImmutableTable.java delete mode 100644 java/src/game/collect/Sets.java delete mode 100644 java/src/game/collect/SparseImmutableTable.java delete mode 100644 java/src/game/collect/StandardTable.java delete mode 100644 java/src/game/collect/Table.java delete mode 100644 java/src/game/collect/TransformedIterator.java delete mode 100644 java/src/game/collect/UnmodifiableIterator.java delete mode 100644 java/src/game/collect/UnmodifiableListIterator.java delete mode 100644 java/src/game/future/AbstractFuture.java delete mode 100644 java/src/game/future/ExecutionError.java delete mode 100644 java/src/game/future/ExecutionList.java delete mode 100644 java/src/game/future/FutureCallback.java delete mode 100644 java/src/game/future/Futures.java delete mode 100644 java/src/game/future/ListenableFuture.java delete mode 100644 java/src/game/future/ListenableFutureTask.java delete mode 100644 java/src/game/future/MoreExecutors.java delete mode 100644 java/src/game/future/ThreadFactoryBuilder.java delete mode 100644 java/src/game/future/UncheckedExecutionException.java delete mode 100644 java/src/game/net/bootstrap/AbstractBootstrap.java delete mode 100644 java/src/game/net/bootstrap/Bootstrap.java delete mode 100644 java/src/game/net/bootstrap/ChannelFactory.java delete mode 100644 java/src/game/net/bootstrap/ServerBootstrap.java delete mode 100644 java/src/game/net/buffer/AbstractByteBuf.java delete mode 100644 java/src/game/net/buffer/AbstractByteBufAllocator.java delete mode 100644 java/src/game/net/buffer/AbstractDerivedByteBuf.java delete mode 100644 java/src/game/net/buffer/AbstractReferenceCountedByteBuf.java delete mode 100644 java/src/game/net/buffer/AdvancedLeakAwareByteBuf.java delete mode 100644 java/src/game/net/buffer/ByteBuf.java delete mode 100644 java/src/game/net/buffer/ByteBufAllocator.java delete mode 100644 java/src/game/net/buffer/ByteBufInputStream.java delete mode 100644 java/src/game/net/buffer/ByteBufOutputStream.java delete mode 100644 java/src/game/net/buffer/ByteBufProcessor.java delete mode 100644 java/src/game/net/buffer/ByteBufUtil.java delete mode 100644 java/src/game/net/buffer/CompositeByteBuf.java delete mode 100644 java/src/game/net/buffer/DuplicatedByteBuf.java delete mode 100644 java/src/game/net/buffer/EmptyByteBuf.java delete mode 100644 java/src/game/net/buffer/PoolArena.java delete mode 100644 java/src/game/net/buffer/PoolChunk.java delete mode 100644 java/src/game/net/buffer/PoolChunkList.java delete mode 100644 java/src/game/net/buffer/PoolSubpage.java delete mode 100644 java/src/game/net/buffer/PoolThreadCache.java delete mode 100644 java/src/game/net/buffer/PooledByteBuf.java delete mode 100644 java/src/game/net/buffer/PooledByteBufAllocator.java delete mode 100644 java/src/game/net/buffer/PooledDirectByteBuf.java delete mode 100644 java/src/game/net/buffer/PooledHeapByteBuf.java delete mode 100644 java/src/game/net/buffer/PooledUnsafeDirectByteBuf.java delete mode 100644 java/src/game/net/buffer/ReadOnlyByteBuf.java delete mode 100644 java/src/game/net/buffer/ReadOnlyByteBufferBuf.java delete mode 100644 java/src/game/net/buffer/ReadOnlyUnsafeDirectByteBuf.java delete mode 100644 java/src/game/net/buffer/SimpleLeakAwareByteBuf.java delete mode 100644 java/src/game/net/buffer/SlicedByteBuf.java delete mode 100644 java/src/game/net/buffer/SwappedByteBuf.java delete mode 100644 java/src/game/net/buffer/Unpooled.java delete mode 100644 java/src/game/net/buffer/UnpooledByteBufAllocator.java delete mode 100644 java/src/game/net/buffer/UnpooledDirectByteBuf.java delete mode 100644 java/src/game/net/buffer/UnpooledHeapByteBuf.java delete mode 100644 java/src/game/net/buffer/UnpooledUnsafeDirectByteBuf.java delete mode 100644 java/src/game/net/buffer/UnreleasableByteBuf.java delete mode 100644 java/src/game/net/buffer/UnsafeDirectSwappedByteBuf.java delete mode 100644 java/src/game/net/buffer/WrappedByteBuf.java delete mode 100644 java/src/game/net/channel/AbstractChannel.java delete mode 100644 java/src/game/net/channel/AbstractChannelHandlerContext.java delete mode 100644 java/src/game/net/channel/AbstractServerChannel.java delete mode 100644 java/src/game/net/channel/AdaptiveRecvByteBufAllocator.java delete mode 100644 java/src/game/net/channel/Channel.java delete mode 100644 java/src/game/net/channel/ChannelConfig.java delete mode 100644 java/src/game/net/channel/ChannelException.java delete mode 100644 java/src/game/net/channel/ChannelFuture.java delete mode 100644 java/src/game/net/channel/ChannelFutureListener.java delete mode 100644 java/src/game/net/channel/ChannelHandler.java delete mode 100644 java/src/game/net/channel/ChannelHandlerAdapter.java delete mode 100644 java/src/game/net/channel/ChannelHandlerContext.java delete mode 100644 java/src/game/net/channel/ChannelInboundHandler.java delete mode 100644 java/src/game/net/channel/ChannelInboundHandlerAdapter.java delete mode 100644 java/src/game/net/channel/ChannelInitializer.java delete mode 100644 java/src/game/net/channel/ChannelMetadata.java delete mode 100644 java/src/game/net/channel/ChannelOption.java delete mode 100644 java/src/game/net/channel/ChannelOutboundBuffer.java delete mode 100644 java/src/game/net/channel/ChannelOutboundHandler.java delete mode 100644 java/src/game/net/channel/ChannelOutboundHandlerAdapter.java delete mode 100644 java/src/game/net/channel/ChannelPipeline.java delete mode 100644 java/src/game/net/channel/ChannelPipelineException.java delete mode 100644 java/src/game/net/channel/ChannelProgressivePromise.java delete mode 100644 java/src/game/net/channel/ChannelPromise.java delete mode 100644 java/src/game/net/channel/CompleteChannelFuture.java delete mode 100644 java/src/game/net/channel/ConnectTimeoutException.java delete mode 100644 java/src/game/net/channel/DefaultChannelConfig.java delete mode 100644 java/src/game/net/channel/DefaultChannelHandlerContext.java delete mode 100644 java/src/game/net/channel/DefaultChannelPipeline.java delete mode 100644 java/src/game/net/channel/DefaultChannelPromise.java delete mode 100644 java/src/game/net/channel/DefaultMessageSizeEstimator.java delete mode 100644 java/src/game/net/channel/EventLoop.java delete mode 100644 java/src/game/net/channel/EventLoopException.java delete mode 100644 java/src/game/net/channel/EventLoopGroup.java delete mode 100644 java/src/game/net/channel/FailedChannelFuture.java delete mode 100644 java/src/game/net/channel/MessageSizeEstimator.java delete mode 100644 java/src/game/net/channel/MultithreadEventLoopGroup.java delete mode 100644 java/src/game/net/channel/RecvByteBufAllocator.java delete mode 100644 java/src/game/net/channel/ServerChannel.java delete mode 100644 java/src/game/net/channel/SimpleChannelInboundHandler.java delete mode 100644 java/src/game/net/channel/SingleThreadEventLoop.java delete mode 100644 java/src/game/net/channel/SucceededChannelFuture.java delete mode 100644 java/src/game/net/channel/VoidChannelPromise.java delete mode 100644 java/src/game/net/channel/local/LocalAddress.java delete mode 100644 java/src/game/net/channel/local/LocalChannel.java delete mode 100644 java/src/game/net/channel/local/LocalChannelRegistry.java delete mode 100644 java/src/game/net/channel/local/LocalEventLoop.java delete mode 100644 java/src/game/net/channel/local/LocalEventLoopGroup.java delete mode 100644 java/src/game/net/channel/local/LocalServerChannel.java delete mode 100644 java/src/game/net/channel/nio/AbstractNioByteChannel.java delete mode 100644 java/src/game/net/channel/nio/AbstractNioChannel.java delete mode 100644 java/src/game/net/channel/nio/AbstractNioMessageChannel.java delete mode 100644 java/src/game/net/channel/nio/NioEventLoop.java delete mode 100644 java/src/game/net/channel/nio/NioEventLoopGroup.java delete mode 100644 java/src/game/net/channel/nio/NioTask.java delete mode 100644 java/src/game/net/channel/nio/SelectedSelectionKeySet.java delete mode 100644 java/src/game/net/channel/socket/ChannelInputShutdownEvent.java delete mode 100644 java/src/game/net/channel/socket/DefaultServerSocketChannelConfig.java delete mode 100644 java/src/game/net/channel/socket/DefaultSocketChannelConfig.java delete mode 100644 java/src/game/net/channel/socket/ServerSocketChannel.java delete mode 100644 java/src/game/net/channel/socket/ServerSocketChannelConfig.java delete mode 100644 java/src/game/net/channel/socket/SocketChannel.java delete mode 100644 java/src/game/net/channel/socket/SocketChannelConfig.java delete mode 100644 java/src/game/net/channel/socket/nio/NioServerSocketChannel.java delete mode 100644 java/src/game/net/channel/socket/nio/NioSocketChannel.java delete mode 100644 java/src/game/net/handler/codec/ByteToMessageDecoder.java delete mode 100644 java/src/game/net/handler/codec/CodecException.java delete mode 100644 java/src/game/net/handler/codec/CorruptedFrameException.java delete mode 100644 java/src/game/net/handler/codec/DecoderException.java delete mode 100644 java/src/game/net/handler/codec/EncoderException.java delete mode 100644 java/src/game/net/handler/codec/MessageToByteEncoder.java delete mode 100644 java/src/game/net/handler/timeout/ReadTimeoutException.java delete mode 100644 java/src/game/net/handler/timeout/ReadTimeoutHandler.java delete mode 100644 java/src/game/net/handler/timeout/TimeoutException.java delete mode 100644 java/src/game/net/util/Attribute.java delete mode 100644 java/src/game/net/util/AttributeKey.java delete mode 100644 java/src/game/net/util/AttributeMap.java delete mode 100644 java/src/game/net/util/CharsetUtil.java delete mode 100644 java/src/game/net/util/DefaultAttributeMap.java delete mode 100644 java/src/game/net/util/IllegalReferenceCountException.java delete mode 100644 java/src/game/net/util/NetUtil.java delete mode 100644 java/src/game/net/util/Recycler.java delete mode 100644 java/src/game/net/util/ReferenceCountUtil.java delete mode 100644 java/src/game/net/util/ReferenceCounted.java delete mode 100644 java/src/game/net/util/ResourceLeak.java delete mode 100644 java/src/game/net/util/ResourceLeakDetector.java delete mode 100644 java/src/game/net/util/Signal.java delete mode 100644 java/src/game/net/util/ThreadDeathWatcher.java delete mode 100644 java/src/game/net/util/UniqueName.java delete mode 100644 java/src/game/net/util/concurrent/AbstractEventExecutor.java delete mode 100644 java/src/game/net/util/concurrent/AbstractEventExecutorGroup.java delete mode 100644 java/src/game/net/util/concurrent/AbstractFuture.java delete mode 100644 java/src/game/net/util/concurrent/BlockingOperationException.java delete mode 100644 java/src/game/net/util/concurrent/CompleteFuture.java delete mode 100644 java/src/game/net/util/concurrent/DefaultEventExecutor.java delete mode 100644 java/src/game/net/util/concurrent/DefaultEventExecutorGroup.java delete mode 100644 java/src/game/net/util/concurrent/DefaultFutureListeners.java delete mode 100644 java/src/game/net/util/concurrent/DefaultProgressivePromise.java delete mode 100644 java/src/game/net/util/concurrent/DefaultPromise.java delete mode 100644 java/src/game/net/util/concurrent/DefaultThreadFactory.java delete mode 100644 java/src/game/net/util/concurrent/EventExecutor.java delete mode 100644 java/src/game/net/util/concurrent/EventExecutorGroup.java delete mode 100644 java/src/game/net/util/concurrent/FailedFuture.java delete mode 100644 java/src/game/net/util/concurrent/FastThreadLocal.java delete mode 100644 java/src/game/net/util/concurrent/FastThreadLocalThread.java delete mode 100644 java/src/game/net/util/concurrent/Future.java delete mode 100644 java/src/game/net/util/concurrent/FutureListener.java delete mode 100644 java/src/game/net/util/concurrent/GenericFutureListener.java delete mode 100644 java/src/game/net/util/concurrent/GenericProgressiveFutureListener.java delete mode 100644 java/src/game/net/util/concurrent/GlobalEventExecutor.java delete mode 100644 java/src/game/net/util/concurrent/ImmediateEventExecutor.java delete mode 100644 java/src/game/net/util/concurrent/ImmediateExecutor.java delete mode 100644 java/src/game/net/util/concurrent/MultithreadEventExecutorGroup.java delete mode 100644 java/src/game/net/util/concurrent/ProgressiveFuture.java delete mode 100644 java/src/game/net/util/concurrent/ProgressivePromise.java delete mode 100644 java/src/game/net/util/concurrent/Promise.java delete mode 100644 java/src/game/net/util/concurrent/PromiseTask.java delete mode 100644 java/src/game/net/util/concurrent/ScheduledFuture.java delete mode 100644 java/src/game/net/util/concurrent/ScheduledFutureTask.java delete mode 100644 java/src/game/net/util/concurrent/SingleThreadEventExecutor.java delete mode 100644 java/src/game/net/util/concurrent/SucceededFuture.java delete mode 100644 java/src/game/net/util/internal/Cleaner0.java delete mode 100644 java/src/game/net/util/internal/EmptyArrays.java delete mode 100644 java/src/game/net/util/internal/IntegerHolder.java delete mode 100644 java/src/game/net/util/internal/InternalThreadLocalMap.java delete mode 100644 java/src/game/net/util/internal/MpscLinkedQueue.java delete mode 100644 java/src/game/net/util/internal/MpscLinkedQueueHeadRef.java delete mode 100644 java/src/game/net/util/internal/MpscLinkedQueueNode.java delete mode 100644 java/src/game/net/util/internal/MpscLinkedQueuePad0.java delete mode 100644 java/src/game/net/util/internal/MpscLinkedQueuePad1.java delete mode 100644 java/src/game/net/util/internal/MpscLinkedQueueTailRef.java delete mode 100644 java/src/game/net/util/internal/NoOpTypeParameterMatcher.java delete mode 100644 java/src/game/net/util/internal/OneTimeTask.java delete mode 100644 java/src/game/net/util/internal/PlatformDependent.java delete mode 100644 java/src/game/net/util/internal/PlatformDependent0.java delete mode 100644 java/src/game/net/util/internal/RecyclableArrayList.java delete mode 100644 java/src/game/net/util/internal/RecyclableMpscLinkedQueueNode.java delete mode 100644 java/src/game/net/util/internal/StringUtil.java delete mode 100644 java/src/game/net/util/internal/SystemPropertyUtil.java delete mode 100644 java/src/game/net/util/internal/ThreadLocalRandom.java delete mode 100644 java/src/game/net/util/internal/TypeParameterMatcher.java delete mode 100644 java/src/game/net/util/internal/UnpaddedInternalThreadLocalMap.java delete mode 100644 java/src/game/net/util/internal/UnsafeAtomicIntegerFieldUpdater.java delete mode 100644 java/src/game/net/util/internal/UnsafeAtomicLongFieldUpdater.java delete mode 100644 java/src/game/net/util/internal/UnsafeAtomicReferenceFieldUpdater.java delete mode 100644 java/src/game/net/util/internal/logging/AbstractInternalLogger.java delete mode 100644 java/src/game/net/util/internal/logging/FormattingTuple.java delete mode 100644 java/src/game/net/util/internal/logging/InternalLogLevel.java delete mode 100644 java/src/game/net/util/internal/logging/InternalLogger.java delete mode 100644 java/src/game/net/util/internal/logging/InternalLoggerFactory.java delete mode 100644 java/src/game/net/util/internal/logging/JdkLogger.java delete mode 100644 java/src/game/net/util/internal/logging/JdkLoggerFactory.java delete mode 100644 java/src/game/net/util/internal/logging/MessageFormatter.java delete mode 100644 java/src/game/util/Predicates.java diff --git a/java/src/game/Game.java b/java/src/game/Game.java index 3886bc0..c6a6916 100755 --- a/java/src/game/Game.java +++ b/java/src/game/Game.java @@ -42,13 +42,17 @@ import java.util.function.Function; import javax.imageio.ImageIO; import javax.swing.JOptionPane; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; + import game.audio.AudioInterface; import game.audio.SoundManager; import game.audio.Volume; import game.biome.Biome; import game.block.Block; -import game.collect.Lists; -import game.collect.Maps; import game.color.Colorizer; import game.color.TextColor; import game.entity.Entity; @@ -56,9 +60,6 @@ import game.entity.animal.EntityHorse; import game.entity.npc.Energy; import game.entity.npc.EntityNPC; import game.entity.types.EntityLiving; -import game.future.Futures; -import game.future.ListenableFuture; -import game.future.ListenableFutureTask; import game.gui.Font; import game.gui.Gui; import game.gui.GuiConsole; diff --git a/java/src/game/Server.java b/java/src/game/Server.java index 7cc3dcc..f3b7dad 100755 --- a/java/src/game/Server.java +++ b/java/src/game/Server.java @@ -16,18 +16,19 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + import game.color.TextColor; import game.dimension.Dimension; import game.dimension.Space; import game.entity.Entity; import game.entity.npc.EntityHuman; import game.entity.npc.EntityNPC; -import game.future.Futures; -import game.future.ListenableFuture; -import game.future.ListenableFutureTask; -import game.future.ThreadFactoryBuilder; import game.init.Config; import game.init.EntityRegistry; import game.init.UniverseRegistry; @@ -35,22 +36,6 @@ import game.log.Log; import game.nbt.NBTLoader; import game.nbt.NBTTagCompound; import game.nbt.NBTTagList; -import game.net.bootstrap.ServerBootstrap; -import game.net.channel.Channel; -import game.net.channel.ChannelException; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelFutureListener; -import game.net.channel.ChannelHandler; -import game.net.channel.ChannelInitializer; -import game.net.channel.ChannelOption; -import game.net.channel.EventLoopGroup; -import game.net.channel.local.LocalAddress; -import game.net.channel.local.LocalServerChannel; -import game.net.channel.nio.NioEventLoopGroup; -import game.net.channel.socket.nio.NioServerSocketChannel; -import game.net.handler.timeout.ReadTimeoutHandler; -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; import game.network.IThreadListener; import game.network.LazyLoadBase; import game.network.NetConnection; @@ -84,6 +69,22 @@ import game.world.PortalType; import game.world.Position; import game.world.Region; import game.world.Region.FolderInfo; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelException; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; import game.world.World; import game.world.WorldPos; import game.world.WorldServer; diff --git a/java/src/game/Temp1.java b/java/src/game/Temp1.java index 8d12128..f717770 100644 --- a/java/src/game/Temp1.java +++ b/java/src/game/Temp1.java @@ -46,7 +46,7 @@ import game.renderer.GlState; import game.renderer.texture.DynamicTexture; import game.renderer.texture.EntityTexManager; import game.renderer.texture.TextureUtil; -import java.util.function.Predicate; +import com.google.common.base.Predicate; public class GuiSkin extends GuiList { @@ -666,7 +666,7 @@ import game.gui.element.Button; import game.gui.element.TextField; import game.network.NetHandlerPlayServer; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.world.Region; public class GuiEdit extends GuiScreen { @@ -739,14 +739,14 @@ public class GuiEdit extends GuiScreen { if(this.player) { this.nameField.setMaxStringLength(16); this.nameField.setValidator(new Predicate() { - public boolean test(String name) { + public boolean apply(String name) { return NetHandlerPlayServer.isValidUser(name); } }); } else { this.nameField.setValidator(new Predicate() { - public boolean test(String name) { + public boolean apply(String name) { for(int z = 0; z < name.length(); z++) { if(GuiCreate.DISALLOWED_CHARS.contains(name.charAt(z))) return false; @@ -821,7 +821,7 @@ import game.gui.element.Button; import game.init.UniverseRegistry; import game.network.NetHandlerPlayServer; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.world.Region; public class GuiCreate extends GuiScreen @@ -856,7 +856,7 @@ public class GuiCreate extends GuiScreen this.worldNameField = new TextField(this.width / 2 - 100, 60, 200, 20); this.worldNameField.setFocused(true); this.worldNameField.setValidator(new Predicate() { - public boolean test(String name) { + public boolean apply(String name) { for(int z = 0; z < name.length(); z++) { if(DISALLOWED_CHARS.contains(name.charAt(z))) return false; @@ -867,7 +867,7 @@ public class GuiCreate extends GuiScreen this.worldUserField = new TextField(this.width / 2 - 100, 98, 200, 20); this.worldUserField.setMaxStringLength(16); this.worldUserField.setValidator(new Predicate() { - public boolean test(String name) { + public boolean apply(String name) { return NetHandlerPlayServer.isValidUser(name); } }); @@ -932,7 +932,7 @@ import game.gui.element.Button; import game.gui.server.GuiMultiplayer.ServerEntry; import game.network.NetHandlerPlayServer; -import java.util.function.Predicate; +import com.google.common.base.Predicate; public class GuiServer extends GuiScreen { private final GuiScreen parentScreen; @@ -963,7 +963,7 @@ public class GuiServer extends GuiScreen { this.serverUserField.setMaxStringLength(16); this.serverUserField.setText(this.serverData.user); this.serverUserField.setValidator(new Predicate() { - public boolean test(String name) { + public boolean apply(String name) { return NetHandlerPlayServer.isValidUser(name); } }); diff --git a/java/src/game/ai/EntityAIAvoidEntity.java b/java/src/game/ai/EntityAIAvoidEntity.java index 8fe4468..edffc96 100755 --- a/java/src/game/ai/EntityAIAvoidEntity.java +++ b/java/src/game/ai/EntityAIAvoidEntity.java @@ -1,13 +1,14 @@ package game.ai; import java.util.List; -import java.util.function.Predicate; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import game.entity.Entity; import game.entity.types.EntityLiving; import game.pathfinding.PathEntity; import game.pathfinding.PathNavigate; -import game.util.Predicates; import game.world.Vec3; public class EntityAIAvoidEntity extends EntityAIBase @@ -38,7 +39,7 @@ public class EntityAIAvoidEntity extends EntityAIBase { this.canBeSeenSelector = new Predicate() { - public boolean test(Entity p_apply_1_) + public boolean apply(Entity p_apply_1_) { return p_apply_1_.isEntityAlive() && EntityAIAvoidEntity.this.theEntity.getEntitySenses().canSee(p_apply_1_); } diff --git a/java/src/game/ai/EntityAIEatGrass.java b/java/src/game/ai/EntityAIEatGrass.java index 4996966..5fa87eb 100755 --- a/java/src/game/ai/EntityAIEatGrass.java +++ b/java/src/game/ai/EntityAIEatGrass.java @@ -1,6 +1,7 @@ package game.ai; -import java.util.function.Predicate; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import game.block.BlockTallGrass; import game.entity.animal.EntitySheep; @@ -8,7 +9,6 @@ import game.init.BlockRegistry; import game.init.Blocks; import game.init.Config; import game.pattern.BlockStateHelper; -import game.util.Predicates; import game.world.BlockPos; import game.world.State; import game.world.World; @@ -40,7 +40,7 @@ public class EntityAIEatGrass extends EntityAIBase else { BlockPos blockpos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ); - return field_179505_b.test(this.entityWorld.getState(blockpos)) ? true : this.entityWorld.getState(blockpos.down()).getBlock() == Blocks.grass; + return field_179505_b.apply(this.entityWorld.getState(blockpos)) ? true : this.entityWorld.getState(blockpos.down()).getBlock() == Blocks.grass; } } @@ -89,7 +89,7 @@ public class EntityAIEatGrass extends EntityAIBase { BlockPos blockpos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ); - if (field_179505_b.test(this.entityWorld.getState(blockpos))) + if (field_179505_b.apply(this.entityWorld.getState(blockpos))) { if (Config.mobGrief) { diff --git a/java/src/game/ai/EntityAIFindEntityNearest.java b/java/src/game/ai/EntityAIFindEntityNearest.java index 5d9af13..d32952e 100755 --- a/java/src/game/ai/EntityAIFindEntityNearest.java +++ b/java/src/game/ai/EntityAIFindEntityNearest.java @@ -2,7 +2,7 @@ package game.ai; import java.util.Collections; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.entity.attributes.AttributeInstance; import game.entity.attributes.Attributes; @@ -28,7 +28,7 @@ public class EntityAIFindEntityNearest extends EntityAIBase this.field_179443_c = new Predicate() { - public boolean test(EntityLiving p_apply_1_) + public boolean apply(EntityLiving p_apply_1_) { double d0 = EntityAIFindEntityNearest.this.getFollowRange(); diff --git a/java/src/game/ai/EntityAIMoveThroughVillage.java b/java/src/game/ai/EntityAIMoveThroughVillage.java index fa7b075..4e9a794 100755 --- a/java/src/game/ai/EntityAIMoveThroughVillage.java +++ b/java/src/game/ai/EntityAIMoveThroughVillage.java @@ -2,7 +2,8 @@ package game.ai; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.types.EntityLiving; import game.pathfinding.PathEntity; import game.pathfinding.PathNavigateGround; diff --git a/java/src/game/ai/EntityAINearestAttackableTarget.java b/java/src/game/ai/EntityAINearestAttackableTarget.java index 3e7ed3b..bde8809 100755 --- a/java/src/game/ai/EntityAINearestAttackableTarget.java +++ b/java/src/game/ai/EntityAINearestAttackableTarget.java @@ -3,7 +3,7 @@ package game.ai; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.entity.Entity; import game.entity.types.EntityLiving; @@ -37,9 +37,9 @@ public class EntityAINearestAttackableTarget extends Ent this.setMutexBits(1); this.targetEntitySelector = new Predicate() { - public boolean test(T p_apply_1_) + public boolean apply(T p_apply_1_) { - if (targetSelector != null && !targetSelector.test(p_apply_1_)) + if (targetSelector != null && !targetSelector.apply(p_apply_1_)) { return false; } diff --git a/java/src/game/ai/EntityAITakePlace.java b/java/src/game/ai/EntityAITakePlace.java index 597bf01..f2447ed 100755 --- a/java/src/game/ai/EntityAITakePlace.java +++ b/java/src/game/ai/EntityAITakePlace.java @@ -2,8 +2,9 @@ package game.ai; import java.util.Map; +import com.google.common.collect.Maps; + import game.block.Block; -import game.collect.Maps; import game.entity.npc.EntityNPC; import game.init.Blocks; import game.init.Config; diff --git a/java/src/game/ai/EntityAITargetNonTamed.java b/java/src/game/ai/EntityAITargetNonTamed.java index 4b9fd5b..26f986c 100755 --- a/java/src/game/ai/EntityAITargetNonTamed.java +++ b/java/src/game/ai/EntityAITargetNonTamed.java @@ -1,6 +1,6 @@ package game.ai; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.entity.types.EntityLiving; import game.entity.types.EntityTameable; diff --git a/java/src/game/ai/EntityAITasks.java b/java/src/game/ai/EntityAITasks.java index 3db2a95..eb26780 100755 --- a/java/src/game/ai/EntityAITasks.java +++ b/java/src/game/ai/EntityAITasks.java @@ -3,7 +3,7 @@ package game.ai; import java.util.Iterator; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; public class EntityAITasks { diff --git a/java/src/game/ai/EntitySenses.java b/java/src/game/ai/EntitySenses.java index 245cafb..a1ae1d9 100755 --- a/java/src/game/ai/EntitySenses.java +++ b/java/src/game/ai/EntitySenses.java @@ -2,7 +2,8 @@ package game.ai; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.Entity; import game.entity.types.EntityLiving; diff --git a/java/src/game/audio/AudioInterface.java b/java/src/game/audio/AudioInterface.java index 3e35423..501dfcf 100644 --- a/java/src/game/audio/AudioInterface.java +++ b/java/src/game/audio/AudioInterface.java @@ -7,10 +7,12 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioFormat.Encoding; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine.Info; + +import com.google.common.collect.Lists; + import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; -import game.collect.Lists; import game.log.Log; public class AudioInterface implements Runnable { diff --git a/java/src/game/audio/SoundManager.java b/java/src/game/audio/SoundManager.java index 4cab800..9c028c5 100755 --- a/java/src/game/audio/SoundManager.java +++ b/java/src/game/audio/SoundManager.java @@ -6,11 +6,12 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.Game; -import game.collect.BiMap; -import game.collect.HashBiMap; -import game.collect.Lists; -import game.collect.Maps; import game.entity.npc.EntityNPC; import game.util.ExtMath; diff --git a/java/src/game/biome/Biome.java b/java/src/game/biome/Biome.java index af3576a..d64c4b0 100755 --- a/java/src/game/biome/Biome.java +++ b/java/src/game/biome/Biome.java @@ -3,13 +3,14 @@ package game.biome; import java.util.List; import java.util.Map; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.Block; import game.block.BlockColored; import game.block.BlockFlower; import game.block.BlockSand; import game.block.BlockTallGrass; -import game.collect.Lists; -import game.collect.Maps; import game.color.Colorizer; import game.color.DyeColor; import game.entity.animal.EntityBat; diff --git a/java/src/game/block/Block.java b/java/src/game/block/Block.java index 9557ca9..651173d 100755 --- a/java/src/game/block/Block.java +++ b/java/src/game/block/Block.java @@ -9,15 +9,16 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import java.util.function.Function; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.UnmodifiableIterator; import game.audio.SoundType; -import game.collect.ImmutableList; -import game.collect.ImmutableMap; -import game.collect.Iterables; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.UnmodifiableIterator; import game.enchantment.EnchantmentHelper; import game.entity.Entity; import game.entity.item.EntityItem; diff --git a/java/src/game/block/BlockButton.java b/java/src/game/block/BlockButton.java index e5a2072..291a465 100755 --- a/java/src/game/block/BlockButton.java +++ b/java/src/game/block/BlockButton.java @@ -2,7 +2,8 @@ package game.block; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.Entity; import game.entity.npc.EntityNPC; import game.entity.projectile.EntityArrow; diff --git a/java/src/game/block/BlockDoor.java b/java/src/game/block/BlockDoor.java index fa7ba17..267a128 100755 --- a/java/src/game/block/BlockDoor.java +++ b/java/src/game/block/BlockDoor.java @@ -2,7 +2,8 @@ package game.block; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.npc.EntityNPC; import game.init.Blocks; import game.init.Items; diff --git a/java/src/game/block/BlockFence.java b/java/src/game/block/BlockFence.java index 87b07fe..8a92095 100755 --- a/java/src/game/block/BlockFence.java +++ b/java/src/game/block/BlockFence.java @@ -2,7 +2,8 @@ package game.block; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.Entity; import game.entity.npc.EntityNPC; import game.item.CheatTab; diff --git a/java/src/game/block/BlockFire.java b/java/src/game/block/BlockFire.java index 95a77ed..b261d30 100755 --- a/java/src/game/block/BlockFire.java +++ b/java/src/game/block/BlockFire.java @@ -2,7 +2,8 @@ package game.block; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.init.Blocks; import game.init.Config; import game.init.SoundEvent; diff --git a/java/src/game/block/BlockFloorPortal.java b/java/src/game/block/BlockFloorPortal.java index e63b77d..bf79ea9 100755 --- a/java/src/game/block/BlockFloorPortal.java +++ b/java/src/game/block/BlockFloorPortal.java @@ -4,7 +4,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; + import game.entity.Entity; import game.item.Item; import game.material.Material; diff --git a/java/src/game/block/BlockFlower.java b/java/src/game/block/BlockFlower.java index 09741c5..3cb4836 100755 --- a/java/src/game/block/BlockFlower.java +++ b/java/src/game/block/BlockFlower.java @@ -2,10 +2,11 @@ package game.block; import java.util.Collection; import java.util.List; -import java.util.function.Predicate; -import game.collect.Filter; -import game.collect.Lists; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; + import game.init.Blocks; import game.init.Config; import game.item.CheatTab; @@ -80,7 +81,7 @@ public abstract class BlockFlower extends BlockBush { this.type = PropertyEnum.create("type", BlockFlower.EnumFlowerType.class, new Predicate() { - public boolean test(BlockFlower.EnumFlowerType p_apply_1_) + public boolean apply(BlockFlower.EnumFlowerType p_apply_1_) { return p_apply_1_.getBlockType() == BlockFlower.this.getBlockType(); } @@ -201,9 +202,9 @@ public abstract class BlockFlower extends BlockBush static { for (final BlockFlower.EnumFlowerColor blockflower$enumflowercolor : BlockFlower.EnumFlowerColor.values()) { - Collection collection = Filter.filter(Lists.newArrayList(values()), new Predicate() + Collection collection = Collections2.filter(Lists.newArrayList(values()), new Predicate() { - public boolean test(BlockFlower.EnumFlowerType p_apply_1_) + public boolean apply(BlockFlower.EnumFlowerType p_apply_1_) { return p_apply_1_.getBlockType() == blockflower$enumflowercolor; } diff --git a/java/src/game/block/BlockHopper.java b/java/src/game/block/BlockHopper.java index ccc4d7e..a2fa8c5 100755 --- a/java/src/game/block/BlockHopper.java +++ b/java/src/game/block/BlockHopper.java @@ -1,7 +1,7 @@ package game.block; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.entity.Entity; import game.entity.npc.EntityNPC; @@ -83,7 +83,7 @@ public class BlockHopper extends BlockContainer public static final PropertyDirection FACING = PropertyDirection.create("facing", new Predicate() { - public boolean test(Facing p_apply_1_) + public boolean apply(Facing p_apply_1_) { return p_apply_1_ != Facing.UP; } diff --git a/java/src/game/block/BlockLeaves.java b/java/src/game/block/BlockLeaves.java index f3c341d..86835e3 100755 --- a/java/src/game/block/BlockLeaves.java +++ b/java/src/game/block/BlockLeaves.java @@ -2,8 +2,9 @@ package game.block; import java.util.List; +import com.google.common.collect.Lists; + import game.audio.SoundType; -import game.collect.Lists; import game.color.Colorizer; import game.entity.npc.EntityNPC; import game.init.Blocks; diff --git a/java/src/game/block/BlockPistonBase.java b/java/src/game/block/BlockPistonBase.java index 4c23aa1..80335aa 100755 --- a/java/src/game/block/BlockPistonBase.java +++ b/java/src/game/block/BlockPistonBase.java @@ -2,8 +2,9 @@ package game.block; import java.util.List; +import com.google.common.collect.Lists; + import game.audio.SoundType; -import game.collect.Lists; import game.entity.Entity; import game.entity.types.EntityLiving; import game.init.Blocks; diff --git a/java/src/game/block/BlockRailBase.java b/java/src/game/block/BlockRailBase.java index d15ad05..ef09fd8 100755 --- a/java/src/game/block/BlockRailBase.java +++ b/java/src/game/block/BlockRailBase.java @@ -2,7 +2,8 @@ package game.block; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.init.Blocks; import game.item.CheatTab; import game.material.Material; diff --git a/java/src/game/block/BlockRailDetector.java b/java/src/game/block/BlockRailDetector.java index 06cf672..022c6ab 100755 --- a/java/src/game/block/BlockRailDetector.java +++ b/java/src/game/block/BlockRailDetector.java @@ -1,7 +1,8 @@ package game.block; import java.util.List; -import java.util.function.Predicate; + +import com.google.common.base.Predicate; import game.entity.Entity; import game.entity.item.EntityCart; @@ -24,7 +25,7 @@ public class BlockRailDetector extends BlockRailBase { public static final PropertyEnum SHAPE = PropertyEnum.create("shape", BlockRailBase.EnumRailDirection.class, new Predicate() { - public boolean test(BlockRailBase.EnumRailDirection p_apply_1_) + public boolean apply(BlockRailBase.EnumRailDirection p_apply_1_) { return p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_WEST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_WEST; } @@ -156,7 +157,7 @@ public class BlockRailDetector extends BlockRailBase // } List list1 = this.findMinecarts(worldIn, pos, EntityCart.class, new Predicate() { - public boolean test(EntityCart entity) { + public boolean apply(EntityCart entity) { return entity instanceof IInventory && entity.isEntityAlive(); } }); diff --git a/java/src/game/block/BlockRailPowered.java b/java/src/game/block/BlockRailPowered.java index 7782ed8..97ce08c 100755 --- a/java/src/game/block/BlockRailPowered.java +++ b/java/src/game/block/BlockRailPowered.java @@ -1,6 +1,6 @@ package game.block; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.properties.IProperty; import game.properties.PropertyBool; @@ -14,7 +14,7 @@ public class BlockRailPowered extends BlockRailBase { public static final PropertyEnum SHAPE = PropertyEnum.create("shape", BlockRailBase.EnumRailDirection.class, new Predicate() { - public boolean test(BlockRailBase.EnumRailDirection p_apply_1_) + public boolean apply(BlockRailBase.EnumRailDirection p_apply_1_) { return p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.NORTH_WEST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_EAST && p_apply_1_ != BlockRailBase.EnumRailDirection.SOUTH_WEST; } diff --git a/java/src/game/block/BlockRedstoneComparator.java b/java/src/game/block/BlockRedstoneComparator.java index 5777d44..b5b2403 100755 --- a/java/src/game/block/BlockRedstoneComparator.java +++ b/java/src/game/block/BlockRedstoneComparator.java @@ -149,7 +149,7 @@ public class BlockRedstoneComparator extends BlockRedstoneDiode implements ITile // { // List list = worldIn.getEntitiesWithinAABB(EntityFrame.class, new BoundingBox((double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 1), (double)(pos.getZ() + 1)), new Predicate() // { -// public boolean test(Entity p_apply_1_) +// public boolean apply(Entity p_apply_1_) // { // return p_apply_1_ != null && p_apply_1_.getHorizontalFacing() == facing; // } diff --git a/java/src/game/block/BlockRedstoneTorch.java b/java/src/game/block/BlockRedstoneTorch.java index 05d63d1..5e0326e 100755 --- a/java/src/game/block/BlockRedstoneTorch.java +++ b/java/src/game/block/BlockRedstoneTorch.java @@ -3,8 +3,9 @@ package game.block; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.init.Blocks; import game.init.ItemRegistry; import game.init.SoundEvent; diff --git a/java/src/game/block/BlockRedstoneWire.java b/java/src/game/block/BlockRedstoneWire.java index 04580ec..d531b0f 100755 --- a/java/src/game/block/BlockRedstoneWire.java +++ b/java/src/game/block/BlockRedstoneWire.java @@ -4,8 +4,9 @@ import java.util.EnumSet; import java.util.List; import java.util.Set; -import game.collect.Lists; -import game.collect.Sets; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + import game.init.Blocks; import game.init.Items; import game.item.Item; diff --git a/java/src/game/block/BlockSapling.java b/java/src/game/block/BlockSapling.java index 6b506ed..2fc5162 100755 --- a/java/src/game/block/BlockSapling.java +++ b/java/src/game/block/BlockSapling.java @@ -2,7 +2,8 @@ package game.block; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.init.Blocks; import game.init.Config; import game.init.WoodType; diff --git a/java/src/game/block/BlockSlab.java b/java/src/game/block/BlockSlab.java index 630da22..46fc27b 100755 --- a/java/src/game/block/BlockSlab.java +++ b/java/src/game/block/BlockSlab.java @@ -2,7 +2,8 @@ package game.block; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.Entity; import game.entity.types.EntityLiving; import game.item.CheatTab; diff --git a/java/src/game/block/BlockStem.java b/java/src/game/block/BlockStem.java index f8b3364..8bd40de 100755 --- a/java/src/game/block/BlockStem.java +++ b/java/src/game/block/BlockStem.java @@ -1,6 +1,6 @@ package game.block; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.init.Blocks; import game.init.Config; @@ -27,7 +27,7 @@ public class BlockStem extends BlockBush implements IGrowable public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 7); public static final PropertyDirection FACING = PropertyDirection.create("facing", new Predicate() { - public boolean test(Facing p_apply_1_) + public boolean apply(Facing p_apply_1_) { return p_apply_1_ != Facing.DOWN; } diff --git a/java/src/game/block/BlockTorch.java b/java/src/game/block/BlockTorch.java index 5aff3b1..3f3df31 100755 --- a/java/src/game/block/BlockTorch.java +++ b/java/src/game/block/BlockTorch.java @@ -1,6 +1,6 @@ package game.block; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.entity.types.EntityLiving; import game.init.Blocks; @@ -28,7 +28,7 @@ public class BlockTorch extends Block { public static final PropertyDirection FACING = PropertyDirection.create("facing", new Predicate() { - public boolean test(Facing p_apply_1_) + public boolean apply(Facing p_apply_1_) { return p_apply_1_ != Facing.DOWN; } diff --git a/java/src/game/clipboard/ClipboardPlacer.java b/java/src/game/clipboard/ClipboardPlacer.java index 5a94c52..bedb874 100755 --- a/java/src/game/clipboard/ClipboardPlacer.java +++ b/java/src/game/clipboard/ClipboardPlacer.java @@ -8,11 +8,12 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.collect.Lists; + import game.block.Block; import game.block.BlockDoor; import game.block.BlockRailBase; import game.block.ITileEntityProvider; -import game.collect.Lists; import game.init.Blocks; import game.init.ReorderRegistry; import game.inventory.IInventory; diff --git a/java/src/game/clipboard/Rotation.java b/java/src/game/clipboard/Rotation.java index f70cb46..3de3cea 100755 --- a/java/src/game/clipboard/Rotation.java +++ b/java/src/game/clipboard/Rotation.java @@ -1,6 +1,6 @@ package game.clipboard; -import java.util.function.Predicate; +import com.google.common.base.Predicate; public class Rotation { private final RotationValue[] values; @@ -9,7 +9,7 @@ public class Rotation { public Rotation(RotationValue[] values, Predicate predicate) { this.values = values; for(int z = 0; z < 16; z++) { - if(predicate != null && !predicate.test(z)) { + if(predicate != null && !predicate.apply(z)) { this.dirFlags[z] = false; continue; } diff --git a/java/src/game/collect/AbstractBiMap.java b/java/src/game/collect/AbstractBiMap.java deleted file mode 100644 index d2c3336..0000000 --- a/java/src/game/collect/AbstractBiMap.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkRemove; -import static game.collect.Preconditions.checkArgument; -import static game.collect.Preconditions.checkState; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -/** - * A general-purpose bimap implementation using any two backing {@code Map} - * instances. - * - *

Note that this class contains {@code equals()} calls that keep it from - * supporting {@code IdentityHashMap} backing maps. - * - * @author Kevin Bourrillion - * @author Mike Bostock - */ - -abstract class AbstractBiMap extends ForwardingMap - implements BiMap, Serializable { - - private transient Map delegate; - transient AbstractBiMap inverse; - - /** Package-private constructor for creating a map-backed bimap. */ - AbstractBiMap(Map forward, Map backward) { - setDelegates(forward, backward); - } - - /** Private constructor for inverse bimap. */ - private AbstractBiMap(Map backward, AbstractBiMap forward) { - delegate = backward; - inverse = forward; - } - - @Override protected Map delegate() { - return delegate; - } - - /** - * Returns its input, or throws an exception if this is not a valid key. - */ - K checkKey(K key) { - return key; - } - - /** - * Returns its input, or throws an exception if this is not a valid value. - */ - V checkValue(V value) { - return value; - } - - /** - * Specifies the delegate maps going in each direction. Called by the - * constructor and by subclasses during deserialization. - */ - void setDelegates(Map forward, Map backward) { - checkState(delegate == null); - checkState(inverse == null); - checkArgument(forward.isEmpty()); - checkArgument(backward.isEmpty()); - checkArgument(forward != backward); - delegate = forward; - inverse = new Inverse(backward, this); - } - - void setInverse(AbstractBiMap inverse) { - this.inverse = inverse; - } - - // Query Operations (optimizations) - - @Override public boolean containsValue(Object value) { - return inverse.containsKey(value); - } - - // Modification Operations - - @Override public V put(K key, V value) { - return putInBothMaps(key, value, false); - } - - @Override - public V forcePut(K key, V value) { - return putInBothMaps(key, value, true); - } - - private V putInBothMaps(K key, V value, boolean force) { - checkKey(key); - checkValue(value); - boolean containedKey = containsKey(key); - if (containedKey && Preconditions.equal(value, get(key))) { - return value; - } - if (force) { - inverse().remove(value); - } else { - checkArgument(!containsValue(value), "value already present: %s", value); - } - V oldValue = delegate.put(key, value); - updateInverseMap(key, containedKey, oldValue, value); - return oldValue; - } - - private void updateInverseMap( - K key, boolean containedKey, V oldValue, V newValue) { - if (containedKey) { - removeFromInverseMap(oldValue); - } - inverse.delegate.put(newValue, key); - } - - @Override public V remove(Object key) { - return containsKey(key) ? removeFromBothMaps(key) : null; - } - - private V removeFromBothMaps(Object key) { - V oldValue = delegate.remove(key); - removeFromInverseMap(oldValue); - return oldValue; - } - - private void removeFromInverseMap(V oldValue) { - inverse.delegate.remove(oldValue); - } - - // Bulk Operations - - @Override public void putAll(Map map) { - for (Entry entry : map.entrySet()) { - put(entry.getKey(), entry.getValue()); - } - } - - @Override public void clear() { - delegate.clear(); - inverse.delegate.clear(); - } - - // Views - - @Override - public BiMap inverse() { - return inverse; - } - - private transient Set keySet; - - @Override public Set keySet() { - Set result = keySet; - return (result == null) ? keySet = new KeySet() : result; - } - - private class KeySet extends ForwardingSet { - @Override protected Set delegate() { - return delegate.keySet(); - } - - @Override public void clear() { - AbstractBiMap.this.clear(); - } - - @Override public boolean remove(Object key) { - if (!contains(key)) { - return false; - } - removeFromBothMaps(key); - return true; - } - - @Override public boolean removeAll(Collection keysToRemove) { - return standardRemoveAll(keysToRemove); - } - - @Override public boolean retainAll(Collection keysToRetain) { - return standardRetainAll(keysToRetain); - } - - @Override public Iterator iterator() { - return Maps.keyIterator(entrySet().iterator()); - } - } - - private transient Set valueSet; - - @Override public Set values() { - /* - * We can almost reuse the inverse's keySet, except we have to fix the - * iteration order so that it is consistent with the forward map. - */ - Set result = valueSet; - return (result == null) ? valueSet = new ValueSet() : result; - } - - private class ValueSet extends ForwardingSet { - final Set valuesDelegate = inverse.keySet(); - - @Override protected Set delegate() { - return valuesDelegate; - } - - @Override public Iterator iterator() { - return Maps.valueIterator(entrySet().iterator()); - } - - @Override public Object[] toArray() { - return standardToArray(); - } - - @Override public T[] toArray(T[] array) { - return standardToArray(array); - } - -// @Override public String toString() { -// return standardToString(); -// } - } - - private transient Set> entrySet; - - @Override public Set> entrySet() { - Set> result = entrySet; - return (result == null) ? entrySet = new EntrySet() : result; - } - - private class EntrySet extends ForwardingSet> { - final Set> esDelegate = delegate.entrySet(); - - @Override protected Set> delegate() { - return esDelegate; - } - - @Override public void clear() { - AbstractBiMap.this.clear(); - } - - @Override public boolean remove(Object object) { - if (!esDelegate.contains(object)) { - return false; - } - - // safe because esDelgate.contains(object). - Entry entry = (Entry) object; - inverse.delegate.remove(entry.getValue()); - /* - * Remove the mapping in inverse before removing from esDelegate because - * if entry is part of esDelegate, entry might be invalidated after the - * mapping is removed from esDelegate. - */ - esDelegate.remove(entry); - return true; - } - - @Override public Iterator> iterator() { - final Iterator> iterator = esDelegate.iterator(); - return new Iterator>() { - Entry entry; - - @Override public boolean hasNext() { - return iterator.hasNext(); - } - - @Override public Entry next() { - entry = iterator.next(); - final Entry finalEntry = entry; - - return new ForwardingMapEntry() { - @Override protected Entry delegate() { - return finalEntry; - } - - @Override public V setValue(V value) { - // Preconditions keep the map and inverse consistent. - checkState(contains(this), "entry no longer in map"); - // similar to putInBothMaps, but set via entry - if (Preconditions.equal(value, getValue())) { - return value; - } - checkArgument(!containsValue(value), - "value already present: %s", value); - V oldValue = finalEntry.setValue(value); - checkState(Preconditions.equal(value, get(getKey())), - "entry no longer in map"); - updateInverseMap(getKey(), true, oldValue, value); - return oldValue; - } - }; - } - - @Override public void remove() { - checkRemove(entry != null); - V value = entry.getValue(); - iterator.remove(); - removeFromInverseMap(value); - } - }; - } - - // See java.util.Collections.CheckedEntrySet for details on attacks. - - @Override public Object[] toArray() { - return standardToArray(); - } - @Override public T[] toArray(T[] array) { - return standardToArray(array); - } - @Override public boolean contains(Object o) { - return Maps.containsEntryImpl(delegate(), o); - } - @Override public boolean containsAll(Collection c) { - return standardContainsAll(c); - } - @Override public boolean removeAll(Collection c) { - return standardRemoveAll(c); - } - @Override public boolean retainAll(Collection c) { - return standardRetainAll(c); - } - } - - /** The inverse of any other {@code AbstractBiMap} subclass. */ - private static class Inverse extends AbstractBiMap { - private Inverse(Map backward, AbstractBiMap forward) { - super(backward, forward); - } - - /* - * Serialization stores the forward bimap, the inverse of this inverse. - * Deserialization calls inverse() on the forward bimap and returns that - * inverse. - * - * If a bimap and its inverse are serialized together, the deserialized - * instances have inverse() methods that return the other. - */ - - @Override - K checkKey(K key) { - return inverse.checkValue(key); - } - - @Override - V checkValue(V value) { - return inverse.checkKey(value); - } - - /** - * @serialData the forward bimap - */ - - private void writeObject(ObjectOutputStream stream) throws IOException { - stream.defaultWriteObject(); - stream.writeObject(inverse()); - } - - - // reading data stored by writeObject - private void readObject(ObjectInputStream stream) - throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - setInverse((AbstractBiMap) stream.readObject()); - } - - - Object readResolve() { - return inverse().inverse(); - } - - - private static final long serialVersionUID = 0; - } - - - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/collect/AbstractIndexedListIterator.java b/java/src/game/collect/AbstractIndexedListIterator.java deleted file mode 100644 index a2056ae..0000000 --- a/java/src/game/collect/AbstractIndexedListIterator.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkPositionIndex; - -import java.util.NoSuchElementException; - -/** - * This class provides a skeletal implementation of the {@link ListIterator} - * interface across a fixed number of elements that may be retrieved by - * position. It does not support {@link #remove}, {@link #set}, or {@link #add}. - * - * @author Jared Levy - */ - -abstract class AbstractIndexedListIterator - extends UnmodifiableListIterator { - private final int size; - private int position; - - /** - * Returns the element with the specified index. This method is called by - * {@link #next()}. - */ - protected abstract E get(int index); - - /** - * Constructs an iterator across a sequence of the given size whose initial - * position is 0. That is, the first call to {@link #next()} will return the - * first element (or throw {@link NoSuchElementException} if {@code size} is - * zero). - * - * @throws IllegalArgumentException if {@code size} is negative - */ - protected AbstractIndexedListIterator(int size) { - this(size, 0); - } - - /** - * Constructs an iterator across a sequence of the given size with the given - * initial position. That is, the first call to {@link #nextIndex()} will - * return {@code position}, and the first call to {@link #next()} will return - * the element at that index, if available. Calls to {@link #previous()} can - * retrieve the preceding {@code position} elements. - * - * @throws IndexOutOfBoundsException if {@code position} is negative or is - * greater than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - protected AbstractIndexedListIterator(int size, int position) { - checkPositionIndex(position, size); - this.size = size; - this.position = position; - } - - @Override - public final boolean hasNext() { - return position < size; - } - - @Override - public final E next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - return get(position++); - } - - @Override - public final int nextIndex() { - return position; - } - - @Override - public final boolean hasPrevious() { - return position > 0; - } - - @Override - public final E previous() { - if (!hasPrevious()) { - throw new NoSuchElementException(); - } - return get(--position); - } - - @Override - public final int previousIndex() { - return position - 1; - } -} diff --git a/java/src/game/collect/AbstractIterator.java b/java/src/game/collect/AbstractIterator.java deleted file mode 100644 index 7ba15e0..0000000 --- a/java/src/game/collect/AbstractIterator.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkState; - -import java.util.NoSuchElementException; - -/** - * This class provides a skeletal implementation of the {@code Iterator} - * interface, to make this interface easier to implement for certain types of - * data sources. - * - *

{@code Iterator} requires its implementations to support querying the - * end-of-data status without changing the iterator's state, using the {@link - * #hasNext} method. But many data sources, such as {@link - * java.io.Reader#read()}, do not expose this information; the only way to - * discover whether there is any data left is by trying to retrieve it. These - * types of data sources are ordinarily difficult to write iterators for. But - * using this class, one must implement only the {@link #computeNext} method, - * and invoke the {@link #endOfData} method when appropriate. - * - *

Another example is an iterator that skips over null elements in a backing - * iterator. This could be implemented as:

   {@code
- *
- *   public static Iterator skipNulls(final Iterator in) {
- *     return new AbstractIterator() {
- *       protected String computeNext() {
- *         while (in.hasNext()) {
- *           String s = in.next();
- *           if (s != null) {
- *             return s;
- *           }
- *         }
- *         return endOfData();
- *       }
- *     };
- *   }}
- * - *

This class supports iterators that include null elements. - * - * @author Kevin Bourrillion - * @since 2.0 (imported from Google Collections Library) - */ -// When making changes to this class, please also update the copy at -// com.google.common.base.AbstractIterator - -public abstract class AbstractIterator extends UnmodifiableIterator { - private State state = State.NOT_READY; - - /** Constructor for use by subclasses. */ - protected AbstractIterator() {} - - private enum State { - /** We have computed the next element and haven't returned it yet. */ - READY, - - /** We haven't yet computed or have already returned the element. */ - NOT_READY, - - /** We have reached the end of the data and are finished. */ - DONE, - - /** We've suffered an exception and are kaput. */ - FAILED, - } - - private T next; - - /** - * Returns the next element. Note: the implementation must call {@link - * #endOfData()} when there are no elements left in the iteration. Failure to - * do so could result in an infinite loop. - * - *

The initial invocation of {@link #hasNext()} or {@link #next()} calls - * this method, as does the first invocation of {@code hasNext} or {@code - * next} following each successful call to {@code next}. Once the - * implementation either invokes {@code endOfData} or throws an exception, - * {@code computeNext} is guaranteed to never be called again. - * - *

If this method throws an exception, it will propagate outward to the - * {@code hasNext} or {@code next} invocation that invoked this method. Any - * further attempts to use the iterator will result in an {@link - * IllegalStateException}. - * - *

The implementation of this method may not invoke the {@code hasNext}, - * {@code next}, or {@link #peek()} methods on this instance; if it does, an - * {@code IllegalStateException} will result. - * - * @return the next element if there was one. If {@code endOfData} was called - * during execution, the return value will be ignored. - * @throws RuntimeException if any unrecoverable error happens. This exception - * will propagate outward to the {@code hasNext()}, {@code next()}, or - * {@code peek()} invocation that invoked this method. Any further - * attempts to use the iterator will result in an - * {@link IllegalStateException}. - */ - protected abstract T computeNext(); - - /** - * Implementations of {@link #computeNext} must invoke this method when - * there are no elements left in the iteration. - * - * @return {@code null}; a convenience so your {@code computeNext} - * implementation can use the simple statement {@code return endOfData();} - */ - protected final T endOfData() { - state = State.DONE; - return null; - } - - @Override - public final boolean hasNext() { - checkState(state != State.FAILED); - switch (state) { - case DONE: - return false; - case READY: - return true; - default: - } - return tryToComputeNext(); - } - - private boolean tryToComputeNext() { - state = State.FAILED; // temporary pessimism - next = computeNext(); - if (state != State.DONE) { - state = State.READY; - return true; - } - return false; - } - - @Override - public final T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - state = State.NOT_READY; - T result = next; - next = null; - return result; - } - - /** - * Returns the next element in the iteration without advancing the iteration, - * according to the contract of {@link PeekingIterator#peek()}. - * - *

Implementations of {@code AbstractIterator} that wish to expose this - * functionality should implement {@code PeekingIterator}. - */ - public final T peek() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - return next; - } -} diff --git a/java/src/game/collect/AbstractMapEntry.java b/java/src/game/collect/AbstractMapEntry.java deleted file mode 100644 index 4c89223..0000000 --- a/java/src/game/collect/AbstractMapEntry.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Map.Entry; - -/** - * Implementation of the {@code equals}, {@code hashCode}, and {@code toString} - * methods of {@code Entry}. - * - * @author Jared Levy - */ - -abstract class AbstractMapEntry implements Entry { - - @Override - public abstract K getKey(); - - @Override - public abstract V getValue(); - - @Override - public V setValue(V value) { - throw new UnsupportedOperationException(); - } - - @Override public boolean equals(Object object) { - if (object instanceof Entry) { - Entry that = (Entry) object; - return Preconditions.equal(this.getKey(), that.getKey()) - && Preconditions.equal(this.getValue(), that.getValue()); - } - return false; - } - - @Override public int hashCode() { - K k = getKey(); - V v = getValue(); - return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode()); - } - - /** - * Returns a string representation of the form {@code {key}={value}}. - */ - @Override public String toString() { - return getKey() + "=" + getValue(); - } -} diff --git a/java/src/game/collect/AbstractTable.java b/java/src/game/collect/AbstractTable.java deleted file mode 100644 index b19ada4..0000000 --- a/java/src/game/collect/AbstractTable.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2013 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package game.collect; - -import java.util.AbstractCollection; -import java.util.AbstractSet; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -/** - * Skeletal, implementation-agnostic implementation of the {@link Table} interface. - * - * @author Louis Wasserman - */ - -abstract class AbstractTable implements Table { - - @Override - public boolean containsRow(Object rowKey) { - return Maps.safeContainsKey(rowMap(), rowKey); - } - - @Override - public boolean containsColumn(Object columnKey) { - return Maps.safeContainsKey(columnMap(), columnKey); - } - - @Override - public Set rowKeySet() { - return rowMap().keySet(); - } - - @Override - public Set columnKeySet() { - return columnMap().keySet(); - } - - @Override - public boolean containsValue(Object value) { - for (Map row : rowMap().values()) { - if (row.containsValue(value)) { - return true; - } - } - return false; - } - - @Override - public boolean contains(Object rowKey, Object columnKey) { - Map row = Maps.safeGet(rowMap(), rowKey); - return row != null && Maps.safeContainsKey(row, columnKey); - } - - @Override - public V get(Object rowKey, Object columnKey) { - Map row = Maps.safeGet(rowMap(), rowKey); - return (row == null) ? null : Maps.safeGet(row, columnKey); - } - - @Override - public boolean isEmpty() { - return size() == 0; - } - - @Override - public void clear() { - Iterators.clear(cellSet().iterator()); - } - - @Override - public V remove(Object rowKey, Object columnKey) { - Map row = Maps.safeGet(rowMap(), rowKey); - return (row == null) ? null : Maps.safeRemove(row, columnKey); - } - - @Override - public V put(R rowKey, C columnKey, V value) { - return row(rowKey).put(columnKey, value); - } - - @Override - public void putAll(Table table) { - for (Table.Cell cell : table.cellSet()) { - put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); - } - } - - private transient Set> cellSet; - - @Override - public Set> cellSet() { - Set> result = cellSet; - return (result == null) ? cellSet = createCellSet() : result; - } - - Set> createCellSet() { - return new CellSet(); - } - - abstract Iterator> cellIterator(); - - class CellSet extends AbstractSet> { - @Override - public boolean contains(Object o) { - if (o instanceof Cell) { - Cell cell = (Cell) o; - Map row = Maps.safeGet(rowMap(), cell.getRowKey()); - return row != null && Filter.safeContains( - row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue())); - } - return false; - } - - @Override - public boolean remove(Object o) { - if (o instanceof Cell) { - Cell cell = (Cell) o; - Map row = Maps.safeGet(rowMap(), cell.getRowKey()); - return row != null && Filter.safeRemove( - row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue())); - } - return false; - } - - @Override - public void clear() { - AbstractTable.this.clear(); - } - - @Override - public Iterator> iterator() { - return cellIterator(); - } - - @Override - public int size() { - return AbstractTable.this.size(); - } - } - - private transient Collection values; - - @Override - public Collection values() { - Collection result = values; - return (result == null) ? values = createValues() : result; - } - - Collection createValues() { - return new Values(); - } - - Iterator valuesIterator() { - return new TransformedIterator, V>(cellSet().iterator()) { - @Override - V transform(Cell cell) { - return cell.getValue(); - } - }; - } - - class Values extends AbstractCollection { - @Override - public Iterator iterator() { - return valuesIterator(); - } - - @Override - public boolean contains(Object o) { - return containsValue(o); - } - - @Override - public void clear() { - AbstractTable.this.clear(); - } - - @Override - public int size() { - return AbstractTable.this.size(); - } - } - - @Override public boolean equals(Object obj) { - return equalsImpl(this, obj); - } - - static boolean equalsImpl(Table table, Object obj) { - if (obj == table) { - return true; - } else if (obj instanceof Table) { - Table that = (Table) obj; - return table.cellSet().equals(that.cellSet()); - } else { - return false; - } - } - - @Override public int hashCode() { - return cellSet().hashCode(); - } - - /** - * Returns the string representation {@code rowMap().toString()}. - */ - @Override public String toString() { - return rowMap().toString(); - } -} diff --git a/java/src/game/collect/BiMap.java b/java/src/game/collect/BiMap.java deleted file mode 100644 index 3b920df..0000000 --- a/java/src/game/collect/BiMap.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Map; -import java.util.Set; - -/** - * A bimap (or "bidirectional map") is a map that preserves the uniqueness of - * its values as well as that of its keys. This constraint enables bimaps to - * support an "inverse view", which is another bimap containing the same entries - * as this bimap but with reversed keys and values. - * - *

See the Guava User Guide article on - * {@code BiMap}. - * - * @author Kevin Bourrillion - * @since 2.0 (imported from Google Collections Library) - */ - -public interface BiMap extends Map { - // Modification Operations - - /** - * {@inheritDoc} - * - * @throws IllegalArgumentException if the given value is already bound to a - * different key in this bimap. The bimap will remain unmodified in this - * event. To avoid this exception, call {@link #forcePut} instead. - */ - @Override - V put(K key, V value); - - /** - * An alternate form of {@code put} that silently removes any existing entry - * with the value {@code value} before proceeding with the {@link #put} - * operation. If the bimap previously contained the provided key-value - * mapping, this method has no effect. - * - *

Note that a successful call to this method could cause the size of the - * bimap to increase by one, stay the same, or even decrease by one. - * - *

Warning: If an existing entry with this value is removed, the key - * for that entry is discarded and not returned. - * - * @param key the key with which the specified value is to be associated - * @param value the value to be associated with the specified key - * @return the value which was previously associated with the key, which may - * be {@code null}, or {@code null} if there was no previous entry - */ - V forcePut(K key, V value); - - // Bulk Operations - - /** - * {@inheritDoc} - * - *

Warning: the results of calling this method may vary depending on - * the iteration order of {@code map}. - * - * @throws IllegalArgumentException if an attempt to {@code put} any - * entry fails. Note that some map entries may have been added to the - * bimap before the exception was thrown. - */ - @Override - void putAll(Map map); - - // Views - - /** - * {@inheritDoc} - * - *

Because a bimap has unique values, this method returns a {@link Set}, - * instead of the {@link java.util.Collection} specified in the {@link Map} - * interface. - */ - @Override - Set values(); - - /** - * Returns the inverse view of this bimap, which maps each of this bimap's - * values to its associated key. The two bimaps are backed by the same data; - * any changes to one will appear in the other. - * - *

Note:There is no guaranteed correspondence between the iteration - * order of a bimap and that of its inverse. - * - * @return the inverse view of this bimap - */ - BiMap inverse(); -} diff --git a/java/src/game/collect/CollectPreconditions.java b/java/src/game/collect/CollectPreconditions.java deleted file mode 100644 index 520d5d2..0000000 --- a/java/src/game/collect/CollectPreconditions.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkState; - -/** - * Precondition checks useful in collection implementations. - */ - -final class CollectPreconditions { - - static void checkEntryNotNull(Object key, Object value) { - if (key == null) { - throw new NullPointerException("null key in entry: null=" + value); - } else if (value == null) { - throw new NullPointerException("null value in entry: " + key + "=null"); - } - } - - static int checkNonnegative(int value, String name) { - if (value < 0) { - throw new IllegalArgumentException(name + " cannot be negative but was: " + value); - } - return value; - } - - /** - * Precondition tester for {@code Iterator.remove()} that throws an exception with a consistent - * error message. - */ - static void checkRemove(boolean canRemove) { - checkState(canRemove, "no calls to next() since the last call to remove()"); - } -} diff --git a/java/src/game/collect/DenseImmutableTable.java b/java/src/game/collect/DenseImmutableTable.java deleted file mode 100644 index 5afd429..0000000 --- a/java/src/game/collect/DenseImmutableTable.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkArgument; - -import java.util.Map; - -/** - * A {@code RegularImmutableTable} optimized for dense data. - */ - -//@Immutable -final class DenseImmutableTable - extends RegularImmutableTable { - private final ImmutableMap rowKeyToIndex; - private final ImmutableMap columnKeyToIndex; - private final ImmutableMap> rowMap; - private final ImmutableMap> columnMap; - private final int[] rowCounts; - private final int[] columnCounts; - private final V[][] values; - private final int[] iterationOrderRow; - private final int[] iterationOrderColumn; - - private static ImmutableMap makeIndex(ImmutableSet set) { - ImmutableMap.Builder indexBuilder = ImmutableMap.builder(); - int i = 0; - for (E key : set) { - indexBuilder.put(key, i); - i++; - } - return indexBuilder.build(); - } - - DenseImmutableTable(ImmutableList> cellList, - ImmutableSet rowSpace, ImmutableSet columnSpace) { - - V[][] array = (V[][]) new Object[rowSpace.size()][columnSpace.size()]; - this.values = array; - this.rowKeyToIndex = makeIndex(rowSpace); - this.columnKeyToIndex = makeIndex(columnSpace); - rowCounts = new int[rowKeyToIndex.size()]; - columnCounts = new int[columnKeyToIndex.size()]; - int[] iterationOrderRow = new int[cellList.size()]; - int[] iterationOrderColumn = new int[cellList.size()]; - for (int i = 0; i < cellList.size(); i++) { - Cell cell = cellList.get(i); - R rowKey = cell.getRowKey(); - C columnKey = cell.getColumnKey(); - int rowIndex = rowKeyToIndex.get(rowKey); - int columnIndex = columnKeyToIndex.get(columnKey); - V existingValue = values[rowIndex][columnIndex]; - checkArgument(existingValue == null, "duplicate key: (%s, %s)", rowKey, columnKey); - values[rowIndex][columnIndex] = cell.getValue(); - rowCounts[rowIndex]++; - columnCounts[columnIndex]++; - iterationOrderRow[i] = rowIndex; - iterationOrderColumn[i] = columnIndex; - } - this.iterationOrderRow = iterationOrderRow; - this.iterationOrderColumn = iterationOrderColumn; - this.rowMap = new RowMap(); - this.columnMap = new ColumnMap(); - } - - /** - * An immutable map implementation backed by an indexed nullable array. - */ - private abstract static class ImmutableArrayMap extends ImmutableMap { - private final int size; - - ImmutableArrayMap(int size) { - this.size = size; - } - - abstract ImmutableMap keyToIndex(); - - // True if getValue never returns null. - private boolean isFull() { - return size == keyToIndex().size(); - } - - K getKey(int index) { - return keyToIndex().keySet().asList().get(index); - } - - abstract V getValue(int keyIndex); - - @Override - ImmutableSet createKeySet() { - return isFull() ? keyToIndex().keySet() : super.createKeySet(); - } - - @Override - public int size() { - return size; - } - - @Override - public V get(Object key) { - Integer keyIndex = keyToIndex().get(key); - return (keyIndex == null) ? null : getValue(keyIndex); - } - - @Override - ImmutableSet> createEntrySet() { - return new ImmutableMapEntrySet() { - @Override ImmutableMap map() { - return ImmutableArrayMap.this; - } - - @Override - public UnmodifiableIterator> iterator() { - return new AbstractIterator>() { - private int index = -1; - private final int maxIndex = keyToIndex().size(); - - @Override - protected Entry computeNext() { - for (index++; index < maxIndex; index++) { - V value = getValue(index); - if (value != null) { - return Maps.immutableEntry(getKey(index), value); - } - } - return endOfData(); - } - }; - } - }; - } - } - - private final class Row extends ImmutableArrayMap { - private final int rowIndex; - - Row(int rowIndex) { - super(rowCounts[rowIndex]); - this.rowIndex = rowIndex; - } - - @Override - ImmutableMap keyToIndex() { - return columnKeyToIndex; - } - - @Override - V getValue(int keyIndex) { - return values[rowIndex][keyIndex]; - } - - @Override - boolean isPartialView() { - return true; - } - } - - private final class Column extends ImmutableArrayMap { - private final int columnIndex; - - Column(int columnIndex) { - super(columnCounts[columnIndex]); - this.columnIndex = columnIndex; - } - - @Override - ImmutableMap keyToIndex() { - return rowKeyToIndex; - } - - @Override - V getValue(int keyIndex) { - return values[keyIndex][columnIndex]; - } - - @Override - boolean isPartialView() { - return true; - } - } - - private final class RowMap extends ImmutableArrayMap> { - private RowMap() { - super(rowCounts.length); - } - - @Override - ImmutableMap keyToIndex() { - return rowKeyToIndex; - } - - @Override - Map getValue(int keyIndex) { - return new Row(keyIndex); - } - - @Override - boolean isPartialView() { - return false; - } - } - - private final class ColumnMap extends ImmutableArrayMap> { - private ColumnMap() { - super(columnCounts.length); - } - - @Override - ImmutableMap keyToIndex() { - return columnKeyToIndex; - } - - @Override - Map getValue(int keyIndex) { - return new Column(keyIndex); - } - - @Override - boolean isPartialView() { - return false; - } - } - - @Override public ImmutableMap> columnMap() { - return columnMap; - } - - @Override - public ImmutableMap> rowMap() { - return rowMap; - } - - @Override public V get(Object rowKey, - Object columnKey) { - Integer rowIndex = rowKeyToIndex.get(rowKey); - Integer columnIndex = columnKeyToIndex.get(columnKey); - return ((rowIndex == null) || (columnIndex == null)) ? null - : values[rowIndex][columnIndex]; - } - - @Override - public int size() { - return iterationOrderRow.length; - } - - @Override - Cell getCell(int index) { - int rowIndex = iterationOrderRow[index]; - int columnIndex = iterationOrderColumn[index]; - R rowKey = rowKeySet().asList().get(rowIndex); - C columnKey = columnKeySet().asList().get(columnIndex); - V value = values[rowIndex][columnIndex]; - return cellOf(rowKey, columnKey, value); - } - - @Override - V getValue(int index) { - return values[iterationOrderRow[index]][iterationOrderColumn[index]]; - } -} diff --git a/java/src/game/collect/EmptyImmutableMap.java b/java/src/game/collect/EmptyImmutableMap.java deleted file mode 100644 index 866868a..0000000 --- a/java/src/game/collect/EmptyImmutableMap.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -/** - * Bimap with no mappings. - * - * @author Jared Levy - */ - -// // uses writeReplace(), not default serialization -final class EmptyImmutableMap extends ImmutableMap { - static final EmptyImmutableMap INSTANCE = new EmptyImmutableMap(); - - private EmptyImmutableMap() {} - -// @Override public ImmutableBiMap inverse() { -// return this; -// } - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public Object get(Object key) { - return null; - } - - @Override - public ImmutableSet> entrySet() { - return ImmutableSet.of(); - } - - @Override - ImmutableSet> createEntrySet() { - throw new AssertionError("should never be called"); - } - -// @Override -// public ImmutableSetMultimap asMultimap() { -// return ImmutableSetMultimap.of(); -// } - - @Override - public ImmutableSet keySet() { - return ImmutableSet.of(); - } - - @Override - boolean isPartialView() { - return false; - } - -// Object readResolve() { -// return INSTANCE; // preserve singleton property -// } - /** - * Returns the empty bimap. - */ - // Casting to any type is safe because the set will never hold any elements. -// -// public static ImmutableBiMap of() { -// return (ImmutableBiMap) EmptyImmutableBiMap.INSTANCE; -// } - - /** - * Returns an immutable bimap containing a single entry. - */ -// public static ImmutableBiMap of(K k1, V v1) { -// return new SingletonImmutableBiMap(k1, v1); -// } - - /** - * Returns an immutable map containing the given entries, in order. - * - * @throws IllegalArgumentException if duplicate keys or values are added - */ -// public static ImmutableBiMap of(K k1, V v1, K k2, V v2) { -// return new RegularImmutableBiMap(entryOf(k1, v1), entryOf(k2, v2)); -// } -// -// /** -// * Returns an immutable map containing the given entries, in order. -// * -// * @throws IllegalArgumentException if duplicate keys or values are added -// */ -// public static ImmutableBiMap of( -// K k1, V v1, K k2, V v2, K k3, V v3) { -// return new RegularImmutableBiMap(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)); -// } -// -// /** -// * Returns an immutable map containing the given entries, in order. -// * -// * @throws IllegalArgumentException if duplicate keys or values are added -// */ -// public static ImmutableBiMap of( -// K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { -// return new RegularImmutableBiMap(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), -// entryOf(k4, v4)); -// } -// -// /** -// * Returns an immutable map containing the given entries, in order. -// * -// * @throws IllegalArgumentException if duplicate keys or values are added -// */ -// public static ImmutableBiMap of( -// K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { -// return new RegularImmutableBiMap(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), -// entryOf(k4, v4), entryOf(k5, v5)); -// } - - // looking for of() with > 5 entries? Use the builder instead. - - /** - * Returns a new builder. The generated builder is equivalent to the builder - * created by the {@link Builder} constructor. - */ -// public static Builder builder() { -// return new Builder(); -// } - - /** - * A builder for creating immutable bimap instances, especially {@code public - * static final} bimaps ("constant bimaps"). Example:
   {@code
-   *
-   *   static final ImmutableBiMap WORD_TO_INT =
-   *       new ImmutableBiMap.Builder()
-   *           .put("one", 1)
-   *           .put("two", 2)
-   *           .put("three", 3)
-   *           .build();}
- * - *

For small immutable bimaps, the {@code ImmutableBiMap.of()} methods - * are even more convenient. - * - *

Builder instances can be reused - it is safe to call {@link #build} - * multiple times to build multiple bimaps in series. Each bimap is a superset - * of the bimaps created before it. - * - * @since 2.0 (imported from Google Collections Library) - */ -// public static final class Builder extends ImmutableMap.Builder { -// -// /** -// * Creates a new builder. The returned builder is equivalent to the builder -// * generated by {@link ImmutableBiMap#builder}. -// */ -// public Builder() {} -// -// /** -// * Associates {@code key} with {@code value} in the built bimap. Duplicate -// * keys or values are not allowed, and will cause {@link #build} to fail. -// */ -// @Override public Builder put(K key, V value) { -// super.put(key, value); -// return this; -// } -// -// /** -// * Associates all of the given map's keys and values in the built bimap. -// * Duplicate keys or values are not allowed, and will cause {@link #build} -// * to fail. -// * -// * @throws NullPointerException if any key or value in {@code map} is null -// */ -// @Override public Builder putAll(Map map) { -// super.putAll(map); -// return this; -// } -// -// /** -// * Returns a newly-created immutable bimap. -// * -// * @throws IllegalArgumentException if duplicate keys or values were added -// */ -// @Override public ImmutableBiMap build() { -// switch (size) { -// case 0: -// return of(); -// case 1: -// return of(entries[0].getKey(), entries[0].getValue()); -// default: -// return new RegularImmutableBiMap(size, entries); -// } -// } -// } - - /** - * Returns an immutable bimap containing the same entries as {@code map}. If - * {@code map} somehow contains entries with duplicate keys (for example, if - * it is a {@code SortedMap} whose comparator is not consistent with - * equals), the results of this method are undefined. - * - *

Despite the method name, this method attempts to avoid actually copying - * the data when it is safe to do so. The exact circumstances under which a - * copy will or will not be performed are undocumented and subject to change. - * - * @throws IllegalArgumentException if two keys have the same value - * @throws NullPointerException if any key or value in {@code map} is null - */ -// public static ImmutableBiMap copyOf( -// Map map) { -// if (map instanceof ImmutableBiMap) { -// // safe since map is not writable -// ImmutableBiMap bimap = (ImmutableBiMap) map; -// // TODO(user): if we need to make a copy of a BiMap because the -// // forward map is a view, don't make a copy of the non-view delegate map -// if (!bimap.isPartialView()) { -// return bimap; -// } -// } -// Entry[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY); -// switch (entries.length) { -// case 0: -// return of(); -// case 1: -// // safe covariant cast in this context -// Entry entry = (Entry) entries[0]; -// return of(entry.getKey(), entry.getValue()); -// default: -// return new RegularImmutableBiMap(entries); -// } -// } - -// private static final Entry[] EMPTY_ENTRY_ARRAY = new Entry[0]; - -// ImmutableBiMap() {} - - /** - * {@inheritDoc} - * - *

The inverse of an {@code ImmutableBiMap} is another - * {@code ImmutableBiMap}. - */ -// @Override -// public abstract ImmutableBiMap inverse(); - - /** - * Returns an immutable set of the values in this map. The values are in the - * same order as the parameters used to build this map. - */ - @Override public ImmutableSet values() { - return ImmutableSet.of(); - } - - /** - * Guaranteed to throw an exception and leave the bimap unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ -// @Deprecated -// @Override -// public V forcePut(K key, V value) { -// throw new UnsupportedOperationException(); -// } - - /** - * Serialized type for all ImmutableBiMap instances. It captures the logical - * contents and they are reconstructed using public factory methods. This - * ensures that the implementation types remain as implementation details. - * - * Since the bimap is immutable, ImmutableBiMap doesn't require special logic - * for keeping the bimap and its inverse in sync during serialization, the way - * AbstractBiMap does. - */ -// private static class SerializedForm extends ImmutableMap.SerializedForm { -// SerializedForm(ImmutableBiMap bimap) { -// super(bimap); -// } -// @Override Object readResolve() { -// Builder builder = new Builder(); -// return createMap(builder); -// } -// private static final long serialVersionUID = 0; -// } -// -// @Override Object writeReplace() { -// return new SerializedForm(this); -// } -} diff --git a/java/src/game/collect/EmptyImmutableSet.java b/java/src/game/collect/EmptyImmutableSet.java deleted file mode 100644 index f86b50f..0000000 --- a/java/src/game/collect/EmptyImmutableSet.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Collection; -import java.util.Set; - -/** - * An empty immutable set. - * - * @author Kevin Bourrillion - */ - -final class EmptyImmutableSet extends ImmutableSet { - static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet(); - - private EmptyImmutableSet() {} - - @Override - public int size() { - return 0; - } - - @Override public boolean isEmpty() { - return true; - } - - @Override public boolean contains(Object target) { - return false; - } - - @Override public boolean containsAll(Collection targets) { - return targets.isEmpty(); - } - - @Override public UnmodifiableIterator iterator() { - return Iterators.emptyIterator(); - } - - @Override boolean isPartialView() { - return false; - } - - @Override - int copyIntoArray(Object[] dst, int offset) { - return offset; - } - - @Override - public ImmutableList asList() { - return ImmutableList.of(); - } - - @Override public boolean equals(Object object) { - if (object instanceof Set) { - Set that = (Set) object; - return that.isEmpty(); - } - return false; - } - - @Override public final int hashCode() { - return 0; - } - - @Override boolean isHashCodeFast() { - return true; - } - - @Override public String toString() { - return "[]"; - } - - Object readResolve() { - return INSTANCE; // preserve singleton property - } - - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/collect/Filter.java b/java/src/game/collect/Filter.java deleted file mode 100644 index c6b384e..0000000 --- a/java/src/game/collect/Filter.java +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkArgument; -import static game.collect.Preconditions.checkNotNull; -import static game.util.Predicates.and; -import static game.util.Predicates.in; -import static game.util.Predicates.not; - -import java.util.AbstractCollection; -import java.util.Collection; -import java.util.Iterator; -import java.util.function.Predicate; - -import game.util.Predicates; - -/** - * Provides static methods for working with {@code Collection} instances. - * - * @author Chris Povirk - * @author Mike Bostock - * @author Jared Levy - * @since 2.0 (imported from Google Collections Library) - */ - -public final class Filter { - private Filter() {} - - /** - * Returns the elements of {@code unfiltered} that satisfy a predicate. The - * returned collection is a live view of {@code unfiltered}; changes to one - * affect the other. - * - *

The resulting collection's iterator does not support {@code remove()}, - * but all other collection methods are supported. When given an element that - * doesn't satisfy the predicate, the collection's {@code add()} and {@code - * addAll()} methods throw an {@link IllegalArgumentException}. When methods - * such as {@code removeAll()} and {@code clear()} are called on the filtered - * collection, only elements that satisfy the filter will be removed from the - * underlying collection. - * - *

The returned collection isn't threadsafe or serializable, even if - * {@code unfiltered} is. - * - *

Many of the filtered collection's methods, such as {@code size()}, - * iterate across every element in the underlying collection and determine - * which elements satisfy the filter. When a live view is not needed, - * it may be faster to copy {@code Iterables.filter(unfiltered, predicate)} - * and use the copy. - * - *

Warning: {@code predicate} must be consistent with equals, - * as documented at {@link Predicate#apply}. Do not provide a predicate such - * as {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent - * with equals. (See {@link Iterables#filter(Iterable, Class)} for related - * functionality.) - */ - // TODO(kevinb): how can we omit that Iterables link when building gwt - // javadoc? - public static Collection filter( - Collection unfiltered, Predicate predicate) { - if (unfiltered instanceof FilteredCollection) { - // Support clear(), removeAll(), and retainAll() when filtering a filtered - // collection. - return ((FilteredCollection) unfiltered).createCombined(predicate); - } - - return new FilteredCollection( - checkNotNull(unfiltered), checkNotNull(predicate)); - } - - /** - * Delegates to {@link Collection#contains}. Returns {@code false} if the - * {@code contains} method throws a {@code ClassCastException} or - * {@code NullPointerException}. - */ - static boolean safeContains( - Collection collection, Object object) { - checkNotNull(collection); - try { - return collection.contains(object); - } catch (ClassCastException e) { - return false; - } catch (NullPointerException e) { - return false; - } - } - - /** - * Delegates to {@link Collection#remove}. Returns {@code false} if the - * {@code remove} method throws a {@code ClassCastException} or - * {@code NullPointerException}. - */ - static boolean safeRemove(Collection collection, Object object) { - checkNotNull(collection); - try { - return collection.remove(object); - } catch (ClassCastException e) { - return false; - } catch (NullPointerException e) { - return false; - } - } - - static class FilteredCollection extends AbstractCollection { - final Collection unfiltered; - final Predicate predicate; - - FilteredCollection(Collection unfiltered, - Predicate predicate) { - this.unfiltered = unfiltered; - this.predicate = predicate; - } - - FilteredCollection createCombined(Predicate newPredicate) { - return new FilteredCollection(unfiltered, - Predicates.and(predicate, newPredicate)); - // . above needed to compile in JDK 5 - } - - @Override - public boolean add(E element) { - checkArgument(predicate.test(element)); - return unfiltered.add(element); - } - - @Override - public boolean addAll(Collection collection) { - for (E element : collection) { - checkArgument(predicate.test(element)); - } - return unfiltered.addAll(collection); - } - - @Override - public void clear() { - Iterables.removeIf(unfiltered, predicate); - } - - @Override - public boolean contains(Object element) { - if (safeContains(unfiltered, element)) { - // element is in unfiltered, so it must be an E - E e = (E) element; - return predicate.test(e); - } - return false; - } - - @Override - public boolean containsAll(Collection collection) { - return containsAllImpl(this, collection); - } - - @Override - public boolean isEmpty() { - return !Iterables.any(unfiltered, predicate); - } - - @Override - public Iterator iterator() { - return Iterators.filter(unfiltered.iterator(), predicate); - } - - @Override - public boolean remove(Object element) { - return contains(element) && unfiltered.remove(element); - } - - @Override - public boolean removeAll(final Collection collection) { - return Iterables.removeIf(unfiltered, and(predicate, in(collection))); - } - - @Override - public boolean retainAll(final Collection collection) { - return Iterables.removeIf(unfiltered, and(predicate, not(in(collection)))); - } - - @Override - public int size() { - return Iterators.size(iterator()); - } - - @Override - public Object[] toArray() { - // creating an ArrayList so filtering happens once - return Lists.newArrayList(iterator()).toArray(); - } - - @Override - public T[] toArray(T[] array) { - return Lists.newArrayList(iterator()).toArray(array); - } - } - - /** - * Returns a collection that applies {@code function} to each element of - * {@code fromCollection}. The returned collection is a live view of {@code - * fromCollection}; changes to one affect the other. - * - *

The returned collection's {@code add()} and {@code addAll()} methods - * throw an {@link UnsupportedOperationException}. All other collection - * methods are supported, as long as {@code fromCollection} supports them. - * - *

The returned collection isn't threadsafe or serializable, even if - * {@code fromCollection} is. - * - *

When a live view is not needed, it may be faster to copy the - * transformed collection and use the copy. - * - *

If the input {@code Collection} is known to be a {@code List}, consider - * {@link Lists#transform}. If only an {@code Iterable} is available, use - * {@link Iterables#transform}. - */ -// public static Collection transform(Collection fromCollection, -// Function function) { -// return new TransformedCollection(fromCollection, function); -// } -// -// static class TransformedCollection extends AbstractCollection { -// final Collection fromCollection; -// final Function function; -// -// TransformedCollection(Collection fromCollection, -// Function function) { -// this.fromCollection = checkNotNull(fromCollection); -// this.function = checkNotNull(function); -// } -// -// @Override public void clear() { -// fromCollection.clear(); -// } -// -// @Override public boolean isEmpty() { -// return fromCollection.isEmpty(); -// } -// -// @Override public Iterator iterator() { -// return Iterators.transform(fromCollection.iterator(), function); -// } -// -// @Override public int size() { -// return fromCollection.size(); -// } -// } - - /** - * Returns {@code true} if the collection {@code self} contains all of the - * elements in the collection {@code c}. - * - *

This method iterates over the specified collection {@code c}, checking - * each element returned by the iterator in turn to see if it is contained in - * the specified collection {@code self}. If all elements are so contained, - * {@code true} is returned, otherwise {@code false}. - * - * @param self a collection which might contain all elements in {@code c} - * @param c a collection whose elements might be contained by {@code self} - */ - static boolean containsAllImpl(Collection self, Collection c) { - return Iterables.all(c, Predicates.in(self)); - } - - /** - * An implementation of {@link Collection#toString()}. - */ -// static String toStringImpl(final Collection collection) { -// StringBuilder sb -// = newStringBuilderForCollection(collection.size()).append('['); -// STANDARD_JOINER.appendTo( -// sb, Iterables.transform(collection, new Function() { -// @Override public Object apply(Object input) { -// return input == collection ? "(this Collection)" : input; -// } -// })); -// return sb.append(']').toString(); -// } -// -// /** -// * Returns best-effort-sized StringBuilder based on the given collection size. -// */ -// static StringBuilder newStringBuilderForCollection(int size) { -// checkNonnegative(size, "size"); -// return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO)); -// } - - /** - * Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 - */ - static Collection cast(Iterable iterable) { - return (Collection) iterable; - } - -// static final Joiner STANDARD_JOINER = Joiner.on(", ").useForNull("null"); - - /** - * Returns a {@link Collection} of all the permutations of the specified - * {@link Iterable}. - * - *

Notes: This is an implementation of the algorithm for - * Lexicographical Permutations Generation, described in Knuth's "The Art of - * Computer Programming", Volume 4, Chapter 7, Section 7.2.1.2. The - * iteration order follows the lexicographical order. This means that - * the first permutation will be in ascending order, and the last will be in - * descending order. - * - *

Duplicate elements are considered equal. For example, the list [1, 1] - * will have only one permutation, instead of two. This is why the elements - * have to implement {@link Comparable}. - * - *

An empty iterable has only one permutation, which is an empty list. - * - *

This method is equivalent to - * {@code Collections2.orderedPermutations(list, Ordering.natural())}. - * - * @param elements the original iterable whose elements have to be permuted. - * @return an immutable {@link Collection} containing all the different - * permutations of the original iterable. - * @throws NullPointerException if the specified iterable is null or has any - * null elements. - * @since 12.0 - */ -// @Beta public static > -// Collection> orderedPermutations(Iterable elements) { -// return orderedPermutations(elements, Ordering.natural()); -// } - - /** - * Returns a {@link Collection} of all the permutations of the specified - * {@link Iterable} using the specified {@link Comparator} for establishing - * the lexicographical ordering. - * - *

Examples:

   {@code
-   *
-   *   for (List perm : orderedPermutations(asList("b", "c", "a"))) {
-   *     println(perm);
-   *   }
-   *   // -> ["a", "b", "c"]
-   *   // -> ["a", "c", "b"]
-   *   // -> ["b", "a", "c"]
-   *   // -> ["b", "c", "a"]
-   *   // -> ["c", "a", "b"]
-   *   // -> ["c", "b", "a"]
-   *
-   *   for (List perm : orderedPermutations(asList(1, 2, 2, 1))) {
-   *     println(perm);
-   *   }
-   *   // -> [1, 1, 2, 2]
-   *   // -> [1, 2, 1, 2]
-   *   // -> [1, 2, 2, 1]
-   *   // -> [2, 1, 1, 2]
-   *   // -> [2, 1, 2, 1]
-   *   // -> [2, 2, 1, 1]}
- * - *

Notes: This is an implementation of the algorithm for - * Lexicographical Permutations Generation, described in Knuth's "The Art of - * Computer Programming", Volume 4, Chapter 7, Section 7.2.1.2. The - * iteration order follows the lexicographical order. This means that - * the first permutation will be in ascending order, and the last will be in - * descending order. - * - *

Elements that compare equal are considered equal and no new permutations - * are created by swapping them. - * - *

An empty iterable has only one permutation, which is an empty list. - * - * @param elements the original iterable whose elements have to be permuted. - * @param comparator a comparator for the iterable's elements. - * @return an immutable {@link Collection} containing all the different - * permutations of the original iterable. - * @throws NullPointerException If the specified iterable is null, has any - * null elements, or if the specified comparator is null. - * @since 12.0 - */ -// @Beta public static Collection> orderedPermutations( -// Iterable elements, Comparator comparator) { -// return new OrderedPermutationCollection(elements, comparator); -// } - -// private static final class OrderedPermutationCollection -// extends AbstractCollection> { -// final ImmutableList inputList; -// final Comparator comparator; -// final int size; -// -// OrderedPermutationCollection(Iterable input, -// Comparator comparator) { -// this.inputList = Ordering.from(comparator).immutableSortedCopy(input); -// this.comparator = comparator; -// this.size = calculateSize(inputList, comparator); -// } -// -// /** -// * The number of permutations with repeated elements is calculated as -// * follows: -// *

    -// *
  • For an empty list, it is 1 (base case).
  • -// *
  • When r numbers are added to a list of n-r elements, the number of -// * permutations is increased by a factor of (n choose r).
  • -// *
-// */ -// private static int calculateSize( -// List sortedInputList, Comparator comparator) { -// long permutations = 1; -// int n = 1; -// int r = 1; -// while (n < sortedInputList.size()) { -// int comparison = comparator.compare( -// sortedInputList.get(n - 1), sortedInputList.get(n)); -// if (comparison < 0) { -// // We move to the next non-repeated element. -// permutations *= binomial(n, r); -// r = 0; -// if (!isPositiveInt(permutations)) { -// return Integer.MAX_VALUE; -// } -// } -// n++; -// r++; -// } -// permutations *= binomial(n, r); -// if (!isPositiveInt(permutations)) { -// return Integer.MAX_VALUE; -// } -// return (int) permutations; -// } -// -// @Override public int size() { -// return size; -// } -// -// @Override public boolean isEmpty() { -// return false; -// } -// -// @Override public Iterator> iterator() { -// return new OrderedPermutationIterator(inputList, comparator); -// } -// -// @Override public boolean contains(Object obj) { -// if (obj instanceof List) { -// List list = (List) obj; -// return isPermutation(inputList, list); -// } -// return false; -// } -// -// @Override public String toString() { -// return "orderedPermutationCollection(" + inputList + ")"; -// } -// } -// -// private static final class OrderedPermutationIterator -// extends AbstractIterator> { -// -// List nextPermutation; -// final Comparator comparator; -// -// OrderedPermutationIterator(List list, -// Comparator comparator) { -// this.nextPermutation = Lists.newArrayList(list); -// this.comparator = comparator; -// } -// -// @Override protected List computeNext() { -// if (nextPermutation == null) { -// return endOfData(); -// } -// ImmutableList next = ImmutableList.copyOf(nextPermutation); -// calculateNextPermutation(); -// return next; -// } -// -// void calculateNextPermutation() { -// int j = findNextJ(); -// if (j == -1) { -// nextPermutation = null; -// return; -// } -// -// int l = findNextL(j); -// Collections.swap(nextPermutation, j, l); -// int n = nextPermutation.size(); -// Collections.reverse(nextPermutation.subList(j + 1, n)); -// } -// -// int findNextJ() { -// for (int k = nextPermutation.size() - 2; k >= 0; k--) { -// if (comparator.compare(nextPermutation.get(k), -// nextPermutation.get(k + 1)) < 0) { -// return k; -// } -// } -// return -1; -// } -// -// int findNextL(int j) { -// E ak = nextPermutation.get(j); -// for (int l = nextPermutation.size() - 1; l > j; l--) { -// if (comparator.compare(ak, nextPermutation.get(l)) < 0) { -// return l; -// } -// } -// throw new AssertionError("this statement should be unreachable"); -// } -// } - - /** - * Returns a {@link Collection} of all the permutations of the specified - * {@link Collection}. - * - *

Notes: This is an implementation of the Plain Changes algorithm - * for permutations generation, described in Knuth's "The Art of Computer - * Programming", Volume 4, Chapter 7, Section 7.2.1.2. - * - *

If the input list contains equal elements, some of the generated - * permutations will be equal. - * - *

An empty collection has only one permutation, which is an empty list. - * - * @param elements the original collection whose elements have to be permuted. - * @return an immutable {@link Collection} containing all the different - * permutations of the original collection. - * @throws NullPointerException if the specified collection is null or has any - * null elements. - * @since 12.0 - */ -// @Beta public static Collection> permutations( -// Collection elements) { -// return new PermutationCollection(ImmutableList.copyOf(elements)); -// } -// -// private static final class PermutationCollection -// extends AbstractCollection> { -// final ImmutableList inputList; -// -// PermutationCollection(ImmutableList input) { -// this.inputList = input; -// } -// -// @Override public int size() { -// return IntMath.factorial(inputList.size()); -// } -// -// @Override public boolean isEmpty() { -// return false; -// } -// -// @Override public Iterator> iterator() { -// return new PermutationIterator(inputList); -// } -// -// @Override public boolean contains(Object obj) { -// if (obj instanceof List) { -// List list = (List) obj; -// return isPermutation(inputList, list); -// } -// return false; -// } -// -// @Override public String toString() { -// return "permutations(" + inputList + ")"; -// } -// } - -// private static class PermutationIterator -// extends AbstractIterator> { -// final List list; -// final int[] c; -// final int[] o; -// int j; -// -// PermutationIterator(List list) { -// this.list = new ArrayList(list); -// int n = list.size(); -// c = new int[n]; -// o = new int[n]; -// Arrays.fill(c, 0); -// Arrays.fill(o, 1); -// j = Integer.MAX_VALUE; -// } -// -// @Override protected List computeNext() { -// if (j <= 0) { -// return endOfData(); -// } -// ImmutableList next = ImmutableList.copyOf(list); -// calculateNextPermutation(); -// return next; -// } -// -// void calculateNextPermutation() { -// j = list.size() - 1; -// int s = 0; -// -// // Handle the special case of an empty list. Skip the calculation of the -// // next permutation. -// if (j == -1) { -// return; -// } -// -// while (true) { -// int q = c[j] + o[j]; -// if (q < 0) { -// switchDirection(); -// continue; -// } -// if (q == j + 1) { -// if (j == 0) { -// break; -// } -// s++; -// switchDirection(); -// continue; -// } -// -// Collections.swap(list, j - c[j] + s, j - q + s); -// c[j] = q; -// break; -// } -// } -// -// void switchDirection() { -// o[j] = -o[j]; -// j--; -// } -// } -// -// /** -// * Returns {@code true} if the second list is a permutation of the first. -// */ -// private static boolean isPermutation(List first, -// List second) { -// if (first.size() != second.size()) { -// return false; -// } -// Multiset firstMultiset = HashMultiset.create(first); -// Multiset secondMultiset = HashMultiset.create(second); -// return firstMultiset.equals(secondMultiset); -// } - -// private static boolean isPositiveInt(long n) { -// return n >= 0 && n <= Integer.MAX_VALUE; -// } -} diff --git a/java/src/game/collect/ForwardingCollection.java b/java/src/game/collect/ForwardingCollection.java deleted file mode 100644 index bc913a3..0000000 --- a/java/src/game/collect/ForwardingCollection.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Collection; -import java.util.Iterator; - -/** - * A collection which forwards all its method calls to another collection. - * Subclasses should override one or more methods to modify the behavior of the - * backing collection as desired per the decorator pattern. - * - *

Warning: The methods of {@code ForwardingCollection} forward - * indiscriminately to the methods of the delegate. For example, - * overriding {@link #add} alone will not change the behavior of {@link - * #addAll}, which can lead to unexpected behavior. In this case, you should - * override {@code addAll} as well, either providing your own implementation, or - * delegating to the provided {@code standardAddAll} method. - * - *

The {@code standard} methods are not guaranteed to be thread-safe, even - * when all of the methods that they depend on are thread-safe. - * - * @author Kevin Bourrillion - * @author Louis Wasserman - * @since 2.0 (imported from Google Collections Library) - */ - -abstract class ForwardingCollection extends ForwardingObject - implements Collection { - // TODO(user): identify places where thread safety is actually lost - - /** Constructor for use by subclasses. */ - protected ForwardingCollection() {} - - @Override protected abstract Collection delegate(); - - @Override - public Iterator iterator() { - return delegate().iterator(); - } - - @Override - public int size() { - return delegate().size(); - } - - @Override - public boolean removeAll(Collection collection) { - return delegate().removeAll(collection); - } - - @Override - public boolean isEmpty() { - return delegate().isEmpty(); - } - - @Override - public boolean contains(Object object) { - return delegate().contains(object); - } - - @Override - public boolean add(E element) { - return delegate().add(element); - } - - @Override - public boolean remove(Object object) { - return delegate().remove(object); - } - - @Override - public boolean containsAll(Collection collection) { - return delegate().containsAll(collection); - } - - @Override - public boolean addAll(Collection collection) { - return delegate().addAll(collection); - } - - @Override - public boolean retainAll(Collection collection) { - return delegate().retainAll(collection); - } - - @Override - public void clear() { - delegate().clear(); - } - - @Override - public Object[] toArray() { - return delegate().toArray(); - } - - @Override - public T[] toArray(T[] array) { - return delegate().toArray(array); - } - - /** - * A sensible definition of {@link #contains} in terms of {@link #iterator}. - * If you override {@link #iterator}, you may wish to override {@link - * #contains} to forward to this implementation. - * - * @since 7.0 - */ - protected boolean standardContains(Object object) { - return Iterators.contains(iterator(), object); - } - - /** - * A sensible definition of {@link #containsAll} in terms of {@link #contains} - * . If you override {@link #contains}, you may wish to override {@link - * #containsAll} to forward to this implementation. - * - * @since 7.0 - */ - protected boolean standardContainsAll(Collection collection) { - return Filter.containsAllImpl(this, collection); - } - - /** - * A sensible definition of {@link #addAll} in terms of {@link #add}. If you - * override {@link #add}, you may wish to override {@link #addAll} to forward - * to this implementation. - * - * @since 7.0 - */ - protected boolean standardAddAll(Collection collection) { - return Iterators.addAll(this, collection.iterator()); - } - - /** - * A sensible definition of {@link #remove} in terms of {@link #iterator}, - * using the iterator's {@code remove} method. If you override {@link - * #iterator}, you may wish to override {@link #remove} to forward to this - * implementation. - * - * @since 7.0 - */ - protected boolean standardRemove(Object object) { - Iterator iterator = iterator(); - while (iterator.hasNext()) { - if (Preconditions.equal(iterator.next(), object)) { - iterator.remove(); - return true; - } - } - return false; - } - - /** - * A sensible definition of {@link #removeAll} in terms of {@link #iterator}, - * using the iterator's {@code remove} method. If you override {@link - * #iterator}, you may wish to override {@link #removeAll} to forward to this - * implementation. - * - * @since 7.0 - */ - protected boolean standardRemoveAll(Collection collection) { - return Iterators.removeAll(iterator(), collection); - } - - /** - * A sensible definition of {@link #retainAll} in terms of {@link #iterator}, - * using the iterator's {@code remove} method. If you override {@link - * #iterator}, you may wish to override {@link #retainAll} to forward to this - * implementation. - * - * @since 7.0 - */ - protected boolean standardRetainAll(Collection collection) { - return Iterators.retainAll(iterator(), collection); - } - - /** - * A sensible definition of {@link #clear} in terms of {@link #iterator}, - * using the iterator's {@code remove} method. If you override {@link - * #iterator}, you may wish to override {@link #clear} to forward to this - * implementation. - * - * @since 7.0 - */ - protected void standardClear() { - Iterators.clear(iterator()); - } - - /** - * A sensible definition of {@link #isEmpty} as {@code !iterator().hasNext}. - * If you override {@link #isEmpty}, you may wish to override {@link #isEmpty} - * to forward to this implementation. Alternately, it may be more efficient to - * implement {@code isEmpty} as {@code size() == 0}. - * - * @since 7.0 - */ - protected boolean standardIsEmpty() { - return !iterator().hasNext(); - } - - /** - * A sensible definition of {@link #toString} in terms of {@link #iterator}. - * If you override {@link #iterator}, you may wish to override {@link - * #toString} to forward to this implementation. - * - * @since 7.0 - */ -// protected String standardToString() { -// return Collections2.toStringImpl(this); -// } - - /** - * A sensible definition of {@link #toArray()} in terms of {@link - * #toArray(Object[])}. If you override {@link #toArray(Object[])}, you may - * wish to override {@link #toArray} to forward to this implementation. - * - * @since 7.0 - */ - protected Object[] standardToArray() { - Object[] newArray = new Object[size()]; - return toArray(newArray); - } - - /** - * A sensible definition of {@link #toArray(Object[])} in terms of {@link - * #size} and {@link #iterator}. If you override either of these methods, you - * may wish to override {@link #toArray} to forward to this implementation. - * - * @since 7.0 - */ - protected T[] standardToArray(T[] array) { - return ObjectArrays.toArrayImpl(this, array); - } -} diff --git a/java/src/game/collect/ForwardingMap.java b/java/src/game/collect/ForwardingMap.java deleted file mode 100644 index b810066..0000000 --- a/java/src/game/collect/ForwardingMap.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -/** - * A map which forwards all its method calls to another map. Subclasses should - * override one or more methods to modify the behavior of the backing map as - * desired per the decorator pattern. - * - *

Warning: The methods of {@code ForwardingMap} forward - * indiscriminately to the methods of the delegate. For example, - * overriding {@link #put} alone will not change the behavior of {@link - * #putAll}, which can lead to unexpected behavior. In this case, you should - * override {@code putAll} as well, either providing your own implementation, or - * delegating to the provided {@code standardPutAll} method. - * - *

Each of the {@code standard} methods, where appropriate, use {@link - * Objects#equal} to test equality for both keys and values. This may not be - * the desired behavior for map implementations that use non-standard notions of - * key equality, such as a {@code SortedMap} whose comparator is not consistent - * with {@code equals}. - * - *

The {@code standard} methods and the collection views they return are not - * guaranteed to be thread-safe, even when all of the methods that they depend - * on are thread-safe. - * - * @author Kevin Bourrillion - * @author Jared Levy - * @author Louis Wasserman - * @since 2.0 (imported from Google Collections Library) - */ - -abstract class ForwardingMap extends ForwardingObject - implements Map { - // TODO(user): identify places where thread safety is actually lost - - /** Constructor for use by subclasses. */ - protected ForwardingMap() {} - - @Override protected abstract Map delegate(); - - @Override - public int size() { - return delegate().size(); - } - - @Override - public boolean isEmpty() { - return delegate().isEmpty(); - } - - @Override - public V remove(Object object) { - return delegate().remove(object); - } - - @Override - public void clear() { - delegate().clear(); - } - - @Override - public boolean containsKey(Object key) { - return delegate().containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return delegate().containsValue(value); - } - - @Override - public V get(Object key) { - return delegate().get(key); - } - - @Override - public V put(K key, V value) { - return delegate().put(key, value); - } - - @Override - public void putAll(Map map) { - delegate().putAll(map); - } - - @Override - public Set keySet() { - return delegate().keySet(); - } - - @Override - public Collection values() { - return delegate().values(); - } - - @Override - public Set> entrySet() { - return delegate().entrySet(); - } - - @Override public boolean equals(Object object) { - return object == this || delegate().equals(object); - } - - @Override public int hashCode() { - return delegate().hashCode(); - } - - /** - * A sensible definition of {@link #putAll(Map)} in terms of {@link - * #put(Object, Object)}. If you override {@link #put(Object, Object)}, you - * may wish to override {@link #putAll(Map)} to forward to this - * implementation. - * - * @since 7.0 - */ -// protected void standardPutAll(Map map) { -// Maps.putAllImpl(this, map); -// } - - /** - * A sensible, albeit inefficient, definition of {@link #remove} in terms of - * the {@code iterator} method of {@link #entrySet}. If you override {@link - * #entrySet}, you may wish to override {@link #remove} to forward to this - * implementation. - * - *

Alternately, you may wish to override {@link #remove} with {@code - * keySet().remove}, assuming that approach would not lead to an infinite - * loop. - * - * @since 7.0 - */ -// @Beta protected V standardRemove(Object key) { -// Iterator> entryIterator = entrySet().iterator(); -// while (entryIterator.hasNext()) { -// Entry entry = entryIterator.next(); -// if (Objects.equal(entry.getKey(), key)) { -// V value = entry.getValue(); -// entryIterator.remove(); -// return value; -// } -// } -// return null; -// } - - /** - * A sensible definition of {@link #clear} in terms of the {@code iterator} - * method of {@link #entrySet}. In many cases, you may wish to override - * {@link #clear} to forward to this implementation. - * - * @since 7.0 - */ -// protected void standardClear() { -// Iterators.clear(entrySet().iterator()); -// } - - /** - * A sensible implementation of {@link Map#keySet} in terms of the following - * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey}, - * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#remove}, {@link - * ForwardingMap#size}, and the {@link Set#iterator} method of {@link - * ForwardingMap#entrySet}. In many cases, you may wish to override {@link - * ForwardingMap#keySet} to forward to this implementation or a subclass - * thereof. - * - * @since 10.0 - */ -// @Beta -// protected class StandardKeySet extends Maps.KeySet { -// /** Constructor for use by subclasses. */ -// public StandardKeySet() { -// super(ForwardingMap.this); -// } -// } - - /** - * A sensible, albeit inefficient, definition of {@link #containsKey} in terms - * of the {@code iterator} method of {@link #entrySet}. If you override {@link - * #entrySet}, you may wish to override {@link #containsKey} to forward to - * this implementation. - * - * @since 7.0 - */ -// @Beta protected boolean standardContainsKey(Object key) { -// return Maps.containsKeyImpl(this, key); -// } - - /** - * A sensible implementation of {@link Map#values} in terms of the following - * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsValue}, - * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#size}, and the {@link - * Set#iterator} method of {@link ForwardingMap#entrySet}. In many cases, you - * may wish to override {@link ForwardingMap#values} to forward to this - * implementation or a subclass thereof. - * - * @since 10.0 - */ -// @Beta -// protected class StandardValues extends Maps.Values { -// /** Constructor for use by subclasses. */ -// public StandardValues() { -// super(ForwardingMap.this); -// } -// } - - /** - * A sensible definition of {@link #containsValue} in terms of the {@code - * iterator} method of {@link #entrySet}. If you override {@link #entrySet}, - * you may wish to override {@link #containsValue} to forward to this - * implementation. - * - * @since 7.0 - */ -// protected boolean standardContainsValue(Object value) { -// return Maps.containsValueImpl(this, value); -// } - - /** - * A sensible implementation of {@link Map#entrySet} in terms of the following - * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey}, - * {@link ForwardingMap#get}, {@link ForwardingMap#isEmpty}, {@link - * ForwardingMap#remove}, and {@link ForwardingMap#size}. In many cases, you - * may wish to override {@link #entrySet} to forward to this implementation - * or a subclass thereof. - * - * @since 10.0 - */ -// @Beta -// protected abstract class StandardEntrySet extends Maps.EntrySet { -// /** Constructor for use by subclasses. */ -// public StandardEntrySet() {} -// -// @Override -// Map map() { -// return ForwardingMap.this; -// } -// } - - /** - * A sensible definition of {@link #isEmpty} in terms of the {@code iterator} - * method of {@link #entrySet}. If you override {@link #entrySet}, you may - * wish to override {@link #isEmpty} to forward to this implementation. - * - * @since 7.0 - */ -// protected boolean standardIsEmpty() { -// return !entrySet().iterator().hasNext(); -// } - - /** - * A sensible definition of {@link #equals} in terms of the {@code equals} - * method of {@link #entrySet}. If you override {@link #entrySet}, you may - * wish to override {@link #equals} to forward to this implementation. - * - * @since 7.0 - */ -// protected boolean standardEquals(Object object) { -// return Maps.equalsImpl(this, object); -// } - - /** - * A sensible definition of {@link #hashCode} in terms of the {@code iterator} - * method of {@link #entrySet}. If you override {@link #entrySet}, you may - * wish to override {@link #hashCode} to forward to this implementation. - * - * @since 7.0 - */ -// protected int standardHashCode() { -// return Sets.hashCodeImpl(entrySet()); -// } - - /** - * A sensible definition of {@link #toString} in terms of the {@code iterator} - * method of {@link #entrySet}. If you override {@link #entrySet}, you may - * wish to override {@link #toString} to forward to this implementation. - * - * @since 7.0 - */ -// protected String standardToString() { -// return Maps.toStringImpl(this); -// } -} diff --git a/java/src/game/collect/ForwardingMapEntry.java b/java/src/game/collect/ForwardingMapEntry.java deleted file mode 100644 index a4f4d03..0000000 --- a/java/src/game/collect/ForwardingMapEntry.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Map; -import java.util.Map.Entry; - -/** - * A map entry which forwards all its method calls to another map entry. - * Subclasses should override one or more methods to modify the behavior of the - * backing map entry as desired per the decorator pattern. - * - *

Warning: The methods of {@code ForwardingMapEntry} forward - * indiscriminately to the methods of the delegate. For example, - * overriding {@link #getValue} alone will not change the behavior of - * {@link #equals}, which can lead to unexpected behavior. In this case, you - * should override {@code equals} as well, either providing your own - * implementation, or delegating to the provided {@code standardEquals} method. - * - *

Each of the {@code standard} methods, where appropriate, use {@link - * Objects#equal} to test equality for both keys and values. This may not be - * the desired behavior for map implementations that use non-standard notions of - * key equality, such as the entry of a {@code SortedMap} whose comparator is - * not consistent with {@code equals}. - * - *

The {@code standard} methods are not guaranteed to be thread-safe, even - * when all of the methods that they depend on are thread-safe. - * - * @author Mike Bostock - * @author Louis Wasserman - * @since 2.0 (imported from Google Collections Library) - */ - -abstract class ForwardingMapEntry - extends ForwardingObject implements Map.Entry { - // TODO(user): identify places where thread safety is actually lost - - /** Constructor for use by subclasses. */ - protected ForwardingMapEntry() {} - - @Override protected abstract Map.Entry delegate(); - - @Override - public K getKey() { - return delegate().getKey(); - } - - @Override - public V getValue() { - return delegate().getValue(); - } - - @Override - public V setValue(V value) { - return delegate().setValue(value); - } - - @Override public boolean equals(Object object) { - return delegate().equals(object); - } - - @Override public int hashCode() { - return delegate().hashCode(); - } - - /** - * A sensible definition of {@link #equals(Object)} in terms of {@link - * #getKey()} and {@link #getValue()}. If you override either of these - * methods, you may wish to override {@link #equals(Object)} to forward to - * this implementation. - * - * @since 7.0 - */ - protected boolean standardEquals(Object object) { - if (object instanceof Entry) { - Entry that = (Entry) object; - return Preconditions.equal(this.getKey(), that.getKey()) - && Preconditions.equal(this.getValue(), that.getValue()); - } - return false; - } - - /** - * A sensible definition of {@link #hashCode()} in terms of {@link #getKey()} - * and {@link #getValue()}. If you override either of these methods, you may - * wish to override {@link #hashCode()} to forward to this implementation. - * - * @since 7.0 - */ -// protected int standardHashCode() { -// K k = getKey(); -// V v = getValue(); -// return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode()); -// } - - /** - * A sensible definition of {@link #toString} in terms of {@link - * #getKey} and {@link #getValue}. If you override either of these - * methods, you may wish to override {@link #equals} to forward to this - * implementation. - * - * @since 7.0 - */ -// @Beta protected String standardToString() { -// return getKey() + "=" + getValue(); -// } -} diff --git a/java/src/game/collect/ForwardingObject.java b/java/src/game/collect/ForwardingObject.java deleted file mode 100644 index d5b64e8..0000000 --- a/java/src/game/collect/ForwardingObject.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -/** - * An abstract base class for implementing the decorator pattern. - * The {@link #delegate()} method must be overridden to return the instance - * being decorated. - * - *

This class does not forward the {@code hashCode} and {@code equals} - * methods through to the backing object, but relies on {@code Object}'s - * implementation. This is necessary to preserve the symmetry of {@code equals}. - * Custom definitions of equality are usually based on an interface, such as - * {@code Set} or {@code List}, so that the implementation of {@code equals} can - * cast the object being tested for equality to the custom interface. {@code - * ForwardingObject} implements no such custom interfaces directly; they - * are implemented only in subclasses. Therefore, forwarding {@code equals} - * would break symmetry, as the forwarding object might consider itself equal to - * the object being tested, but the reverse could not be true. This behavior is - * consistent with the JDK's collection wrappers, such as - * {@link java.util.Collections#unmodifiableCollection}. Use an - * interface-specific subclass of {@code ForwardingObject}, such as {@link - * ForwardingList}, to preserve equality behavior, or override {@code equals} - * directly. - * - *

The {@code toString} method is forwarded to the delegate. Although this - * class does not implement {@link Serializable}, a serializable subclass may be - * created since this class has a parameter-less constructor. - * - * @author Mike Bostock - * @since 2.0 (imported from Google Collections Library) - */ - -abstract class ForwardingObject { - - /** Constructor for use by subclasses. */ - protected ForwardingObject() {} - - /** - * Returns the backing delegate instance that methods are forwarded to. - * Abstract subclasses generally override this method with an abstract method - * that has a more specific return type, such as {@link - * ForwardingSet#delegate}. Concrete subclasses override this method to supply - * the instance being decorated. - */ - protected abstract Object delegate(); - - /** - * Returns the string representation generated by the delegate's - * {@code toString} method. - */ - @Override public String toString() { - return delegate().toString(); - } - - /* No equals or hashCode. See class comments for details. */ -} diff --git a/java/src/game/collect/ForwardingSet.java b/java/src/game/collect/ForwardingSet.java deleted file mode 100644 index 39e87db..0000000 --- a/java/src/game/collect/ForwardingSet.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkNotNull; - -import java.util.Collection; -import java.util.Set; - -/** - * A set which forwards all its method calls to another set. Subclasses should - * override one or more methods to modify the behavior of the backing set as - * desired per the decorator pattern. - * - *

Warning: The methods of {@code ForwardingSet} forward - * indiscriminately to the methods of the delegate. For example, - * overriding {@link #add} alone will not change the behavior of {@link - * #addAll}, which can lead to unexpected behavior. In this case, you should - * override {@code addAll} as well, either providing your own implementation, or - * delegating to the provided {@code standardAddAll} method. - * - *

The {@code standard} methods are not guaranteed to be thread-safe, even - * when all of the methods that they depend on are thread-safe. - * - * @author Kevin Bourrillion - * @author Louis Wasserman - * @since 2.0 (imported from Google Collections Library) - */ - -abstract class ForwardingSet extends ForwardingCollection - implements Set { - // TODO(user): identify places where thread safety is actually lost - - /** Constructor for use by subclasses. */ - protected ForwardingSet() {} - - @Override protected abstract Set delegate(); - - @Override public boolean equals(Object object) { - return object == this || delegate().equals(object); - } - - @Override public int hashCode() { - return delegate().hashCode(); - } - - /** - * A sensible definition of {@link #removeAll} in terms of {@link #iterator} - * and {@link #remove}. If you override {@code iterator} or {@code remove}, - * you may wish to override {@link #removeAll} to forward to this - * implementation. - * - * @since 7.0 (this version overrides the {@code ForwardingCollection} version as of 12.0) - */ - @Override - protected boolean standardRemoveAll(Collection collection) { - return Sets.removeAllImpl(this, checkNotNull(collection)); // for GWT - } - - /** - * A sensible definition of {@link #equals} in terms of {@link #size} and - * {@link #containsAll}. If you override either of those methods, you may wish - * to override {@link #equals} to forward to this implementation. - * - * @since 7.0 - */ - protected boolean standardEquals(Object object) { - return Sets.equalsImpl(this, object); - } - - /** - * A sensible definition of {@link #hashCode} in terms of {@link #iterator}. - * If you override {@link #iterator}, you may wish to override {@link #equals} - * to forward to this implementation. - * - * @since 7.0 - */ - protected int standardHashCode() { - return Sets.hashCodeImpl(this); - } -} diff --git a/java/src/game/collect/HashBiMap.java b/java/src/game/collect/HashBiMap.java deleted file mode 100644 index e816a22..0000000 --- a/java/src/game/collect/HashBiMap.java +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkNonnegative; -import static game.collect.CollectPreconditions.checkRemove; -import static game.collect.Preconditions.checkArgument; - -import java.io.Serializable; -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * A {@link BiMap} backed by two hash tables. This implementation allows null keys and values. A - * {@code HashBiMap} and its inverse are both serializable. - * - *

See the Guava User Guide article on {@code BiMap} - * . - * - * @author Louis Wasserman - * @author Mike Bostock - * @since 2.0 (imported from Google Collections Library) - */ - -public final class HashBiMap extends AbstractMap implements BiMap, Serializable { - - /** - * Returns a new, empty {@code HashBiMap} with the default initial capacity (16). - */ - public static HashBiMap create() { - return create(16); - } - - /** - * Constructs a new, empty bimap with the specified expected size. - * - * @param expectedSize the expected number of entries - * @throws IllegalArgumentException if the specified expected size is negative - */ - public static HashBiMap create(int expectedSize) { - return new HashBiMap(expectedSize); - } - - /** - * Constructs a new bimap containing initial values from {@code map}. The bimap is created with an - * initial capacity sufficient to hold the mappings in the specified map. - */ - public static HashBiMap create(Map map) { - HashBiMap bimap = create(map.size()); - bimap.putAll(map); - return bimap; - } - - private static final class BiEntry extends ImmutableEntry { - final int keyHash; - final int valueHash; - - - BiEntry nextInKToVBucket; - - - BiEntry nextInVToKBucket; - - BiEntry(K key, int keyHash, V value, int valueHash) { - super(key, value); - this.keyHash = keyHash; - this.valueHash = valueHash; - } - } - - private static final double LOAD_FACTOR = 1.0; - - private transient BiEntry[] hashTableKToV; - private transient BiEntry[] hashTableVToK; - private transient int size; - private transient int mask; - private transient int modCount; - - private HashBiMap(int expectedSize) { - init(expectedSize); - } - - private void init(int expectedSize) { - checkNonnegative(expectedSize, "expectedSize"); - int tableSize = Hashing.closedTableSize(expectedSize, LOAD_FACTOR); - this.hashTableKToV = createTable(tableSize); - this.hashTableVToK = createTable(tableSize); - this.mask = tableSize - 1; - this.modCount = 0; - this.size = 0; - } - - /** - * Finds and removes {@code entry} from the bucket linked lists in both the - * key-to-value direction and the value-to-key direction. - */ - private void delete(BiEntry entry) { - int keyBucket = entry.keyHash & mask; - BiEntry prevBucketEntry = null; - for (BiEntry bucketEntry = hashTableKToV[keyBucket]; true; - bucketEntry = bucketEntry.nextInKToVBucket) { - if (bucketEntry == entry) { - if (prevBucketEntry == null) { - hashTableKToV[keyBucket] = entry.nextInKToVBucket; - } else { - prevBucketEntry.nextInKToVBucket = entry.nextInKToVBucket; - } - break; - } - prevBucketEntry = bucketEntry; - } - - int valueBucket = entry.valueHash & mask; - prevBucketEntry = null; - for (BiEntry bucketEntry = hashTableVToK[valueBucket];; - bucketEntry = bucketEntry.nextInVToKBucket) { - if (bucketEntry == entry) { - if (prevBucketEntry == null) { - hashTableVToK[valueBucket] = entry.nextInVToKBucket; - } else { - prevBucketEntry.nextInVToKBucket = entry.nextInVToKBucket; - } - break; - } - prevBucketEntry = bucketEntry; - } - - size--; - modCount++; - } - - private void insert(BiEntry entry) { - int keyBucket = entry.keyHash & mask; - entry.nextInKToVBucket = hashTableKToV[keyBucket]; - hashTableKToV[keyBucket] = entry; - - int valueBucket = entry.valueHash & mask; - entry.nextInVToKBucket = hashTableVToK[valueBucket]; - hashTableVToK[valueBucket] = entry; - - size++; - modCount++; - } - - private static int hash(Object o) { - return Hashing.smear((o == null) ? 0 : o.hashCode()); - } - - private BiEntry seekByKey(Object key, int keyHash) { - for (BiEntry entry = hashTableKToV[keyHash & mask]; entry != null; - entry = entry.nextInKToVBucket) { - if (keyHash == entry.keyHash && Preconditions.equal(key, entry.key)) { - return entry; - } - } - return null; - } - - private BiEntry seekByValue(Object value, int valueHash) { - for (BiEntry entry = hashTableVToK[valueHash & mask]; entry != null; - entry = entry.nextInVToKBucket) { - if (valueHash == entry.valueHash && Preconditions.equal(value, entry.value)) { - return entry; - } - } - return null; - } - - @Override - public boolean containsKey(Object key) { - return seekByKey(key, hash(key)) != null; - } - - @Override - public boolean containsValue(Object value) { - return seekByValue(value, hash(value)) != null; - } - - - @Override - public V get(Object key) { - BiEntry entry = seekByKey(key, hash(key)); - return (entry == null) ? null : entry.value; - } - - @Override - public V put(K key, V value) { - return put(key, value, false); - } - - @Override - public V forcePut(K key, V value) { - return put(key, value, true); - } - - private V put(K key, V value, boolean force) { - int keyHash = hash(key); - int valueHash = hash(value); - - BiEntry oldEntryForKey = seekByKey(key, keyHash); - if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash - && Preconditions.equal(value, oldEntryForKey.value)) { - return value; - } - - BiEntry oldEntryForValue = seekByValue(value, valueHash); - if (oldEntryForValue != null) { - if (force) { - delete(oldEntryForValue); - } else { - throw new IllegalArgumentException("value already present: " + value); - } - } - - if (oldEntryForKey != null) { - delete(oldEntryForKey); - } - BiEntry newEntry = new BiEntry(key, keyHash, value, valueHash); - insert(newEntry); - rehashIfNecessary(); - return (oldEntryForKey == null) ? null : oldEntryForKey.value; - } - - - private K putInverse(V value, K key, boolean force) { - int valueHash = hash(value); - int keyHash = hash(key); - - BiEntry oldEntryForValue = seekByValue(value, valueHash); - if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash - && Preconditions.equal(key, oldEntryForValue.key)) { - return key; - } - - BiEntry oldEntryForKey = seekByKey(key, keyHash); - if (oldEntryForKey != null) { - if (force) { - delete(oldEntryForKey); - } else { - throw new IllegalArgumentException("value already present: " + key); - } - } - - if (oldEntryForValue != null) { - delete(oldEntryForValue); - } - BiEntry newEntry = new BiEntry(key, keyHash, value, valueHash); - insert(newEntry); - rehashIfNecessary(); - return (oldEntryForValue == null) ? null : oldEntryForValue.key; - } - - private void rehashIfNecessary() { - BiEntry[] oldKToV = hashTableKToV; - if (Hashing.needsResizing(size, oldKToV.length, LOAD_FACTOR)) { - int newTableSize = oldKToV.length * 2; - - this.hashTableKToV = createTable(newTableSize); - this.hashTableVToK = createTable(newTableSize); - this.mask = newTableSize - 1; - this.size = 0; - - for (int bucket = 0; bucket < oldKToV.length; bucket++) { - BiEntry entry = oldKToV[bucket]; - while (entry != null) { - BiEntry nextEntry = entry.nextInKToVBucket; - insert(entry); - entry = nextEntry; - } - } - this.modCount++; - } - } - - - private BiEntry[] createTable(int length) { - return new BiEntry[length]; - } - - @Override - public V remove(Object key) { - BiEntry entry = seekByKey(key, hash(key)); - if (entry == null) { - return null; - } else { - delete(entry); - return entry.value; - } - } - - @Override - public void clear() { - size = 0; - Arrays.fill(hashTableKToV, null); - Arrays.fill(hashTableVToK, null); - modCount++; - } - - @Override - public int size() { - return size; - } - - abstract class Itr implements Iterator { - int nextBucket = 0; - BiEntry next = null; - BiEntry toRemove = null; - int expectedModCount = modCount; - - private void checkForConcurrentModification() { - if (modCount != expectedModCount) { - throw new ConcurrentModificationException(); - } - } - - @Override - public boolean hasNext() { - checkForConcurrentModification(); - if (next != null) { - return true; - } - while (nextBucket < hashTableKToV.length) { - if (hashTableKToV[nextBucket] != null) { - next = hashTableKToV[nextBucket++]; - return true; - } - nextBucket++; - } - return false; - } - - @Override - public T next() { - checkForConcurrentModification(); - if (!hasNext()) { - throw new NoSuchElementException(); - } - - BiEntry entry = next; - next = entry.nextInKToVBucket; - toRemove = entry; - return output(entry); - } - - @Override - public void remove() { - checkForConcurrentModification(); - checkRemove(toRemove != null); - delete(toRemove); - expectedModCount = modCount; - toRemove = null; - } - - abstract T output(BiEntry entry); - } - - @Override - public Set keySet() { - return new KeySet(); - } - - private final class KeySet extends Maps.KeySet { - KeySet() { - super(HashBiMap.this); - } - - @Override - public Iterator iterator() { - return new Itr() { - @Override - K output(BiEntry entry) { - return entry.key; - } - }; - } - - @Override - public boolean remove(Object o) { - BiEntry entry = seekByKey(o, hash(o)); - if (entry == null) { - return false; - } else { - delete(entry); - return true; - } - } - } - - @Override - public Set values() { - return inverse().keySet(); - } - - @Override - public Set> entrySet() { - return new EntrySet(); - } - - private final class EntrySet extends Maps.EntrySet { - @Override - Map map() { - return HashBiMap.this; - } - - @Override - public Iterator> iterator() { - return new Itr>() { - @Override - Entry output(BiEntry entry) { - return new MapEntry(entry); - } - - class MapEntry extends AbstractMapEntry { - BiEntry delegate; - - MapEntry(BiEntry entry) { - this.delegate = entry; - } - - @Override public K getKey() { - return delegate.key; - } - - @Override public V getValue() { - return delegate.value; - } - - @Override public V setValue(V value) { - V oldValue = delegate.value; - int valueHash = hash(value); - if (valueHash == delegate.valueHash && Preconditions.equal(value, oldValue)) { - return value; - } - checkArgument( - seekByValue(value, valueHash) == null, "value already present: %s", value); - delete(delegate); - BiEntry newEntry = - new BiEntry(delegate.key, delegate.keyHash, value, valueHash); - insert(newEntry); - expectedModCount = modCount; - if (toRemove == delegate) { - toRemove = newEntry; - } - delegate = newEntry; - return oldValue; - } - } - }; - } - } - - private transient BiMap inverse; - - @Override - public BiMap inverse() { - return (inverse == null) ? inverse = new Inverse() : inverse; - } - - private final class Inverse extends AbstractMap implements BiMap, Serializable { - BiMap forward() { - return HashBiMap.this; - } - - @Override - public int size() { - return size; - } - - @Override - public void clear() { - forward().clear(); - } - - @Override - public boolean containsKey(Object value) { - return forward().containsValue(value); - } - - @Override - public K get(Object value) { - BiEntry entry = seekByValue(value, hash(value)); - return (entry == null) ? null : entry.key; - } - - @Override - public K put(V value, K key) { - return putInverse(value, key, false); - } - - @Override - public K forcePut(V value, K key) { - return putInverse(value, key, true); - } - - @Override - public K remove(Object value) { - BiEntry entry = seekByValue(value, hash(value)); - if (entry == null) { - return null; - } else { - delete(entry); - return entry.key; - } - } - - @Override - public BiMap inverse() { - return forward(); - } - - @Override - public Set keySet() { - return new InverseKeySet(); - } - - private final class InverseKeySet extends Maps.KeySet { - InverseKeySet() { - super(Inverse.this); - } - - @Override - public boolean remove(Object o) { - BiEntry entry = seekByValue(o, hash(o)); - if (entry == null) { - return false; - } else { - delete(entry); - return true; - } - } - - @Override - public Iterator iterator() { - return new Itr() { - @Override V output(BiEntry entry) { - return entry.value; - } - }; - } - } - - @Override - public Set values() { - return forward().keySet(); - } - - @Override - public Set> entrySet() { - return new Maps.EntrySet() { - - @Override - Map map() { - return Inverse.this; - } - - @Override - public Iterator> iterator() { - return new Itr>() { - @Override - Entry output(BiEntry entry) { - return new InverseEntry(entry); - } - - class InverseEntry extends AbstractMapEntry { - BiEntry delegate; - - InverseEntry(BiEntry entry) { - this.delegate = entry; - } - - @Override - public V getKey() { - return delegate.value; - } - - @Override - public K getValue() { - return delegate.key; - } - - @Override - public K setValue(K key) { - K oldKey = delegate.key; - int keyHash = hash(key); - if (keyHash == delegate.keyHash && Preconditions.equal(key, oldKey)) { - return key; - } - checkArgument(seekByKey(key, keyHash) == null, "value already present: %s", key); - delete(delegate); - BiEntry newEntry = - new BiEntry(key, keyHash, delegate.value, delegate.valueHash); - insert(newEntry); - expectedModCount = modCount; - // This is safe because entries can only get bumped up to earlier in the iteration, - // so they can't get revisited. - return oldKey; - } - } - }; - } - }; - } - - Object writeReplace() { - return new InverseSerializedForm(HashBiMap.this); - } - } - - private static final class InverseSerializedForm implements Serializable { - private final HashBiMap bimap; - - InverseSerializedForm(HashBiMap bimap) { - this.bimap = bimap; - } - - Object readResolve() { - return bimap.inverse(); - } - } - - /** - * @serialData the number of entries, first key, first value, second key, second value, and so on. - */ -// -// private void writeObject(ObjectOutputStream stream) throws IOException { -// stream.defaultWriteObject(); -// Serialization.writeMap(this, stream); -// } -// -// -// private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { -// stream.defaultReadObject(); -// int size = Serialization.readCount(stream); -// init(size); -// Serialization.populateMap(this, stream, size); -// } - - - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/collect/Hashing.java b/java/src/game/collect/Hashing.java deleted file mode 100644 index 0ce6f8d..0000000 --- a/java/src/game/collect/Hashing.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -/** - * Static methods for implementing hash-based collections. - * - * @author Kevin Bourrillion - * @author Jesse Wilson - * @author Austin Appleby - */ - -final class Hashing { - private Hashing() {} - - private static final int C1 = 0xcc9e2d51; - private static final int C2 = 0x1b873593; - - /* - * This method was rewritten in Java from an intermediate step of the Murmur hash function in - * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, which contained the - * following header: - * - * MurmurHash3 was written by Austin Appleby, and is placed in the public domain. The author - * hereby disclaims copyright to this source code. - */ - static int smear(int hashCode) { - return C2 * Integer.rotateLeft(hashCode * C1, 15); - } - - static int smearedHash(Object o) { - return smear((o == null) ? 0 : o.hashCode()); - } - - private static int MAX_TABLE_SIZE = 1 << (Integer.SIZE - 2); - - static int closedTableSize(int expectedEntries, double loadFactor) { - // Get the recommended table size. - // Round down to the nearest power of 2. - expectedEntries = Math.max(expectedEntries, 2); - int tableSize = Integer.highestOneBit(expectedEntries); - // Check to make sure that we will not exceed the maximum load factor. - if (expectedEntries > (int) (loadFactor * tableSize)) { - tableSize <<= 1; - return (tableSize > 0) ? tableSize : MAX_TABLE_SIZE; - } - return tableSize; - } - - static boolean needsResizing(int size, int tableSize, double loadFactor) { - return size > loadFactor * tableSize && tableSize < MAX_TABLE_SIZE; - } -} diff --git a/java/src/game/collect/ImmutableAsList.java b/java/src/game/collect/ImmutableAsList.java deleted file mode 100644 index c65f53e..0000000 --- a/java/src/game/collect/ImmutableAsList.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; -import java.io.Serializable; - -/** - * List returned by {@link ImmutableCollection#asList} that delegates {@code contains} checks - * to the backing collection. - * - * @author Jared Levy - * @author Louis Wasserman - */ - - -abstract class ImmutableAsList extends ImmutableList { - abstract ImmutableCollection delegateCollection(); - - @Override public boolean contains(Object target) { - // The collection's contains() is at least as fast as ImmutableList's - // and is often faster. - return delegateCollection().contains(target); - } - - @Override - public int size() { - return delegateCollection().size(); - } - - @Override - public boolean isEmpty() { - return delegateCollection().isEmpty(); - } - - @Override - boolean isPartialView() { - return delegateCollection().isPartialView(); - } - - /** - * Serialized form that leads to the same performance as the original list. - */ - - static class SerializedForm implements Serializable { - final ImmutableCollection collection; - SerializedForm(ImmutableCollection collection) { - this.collection = collection; - } - Object readResolve() { - return collection.asList(); - } - private static final long serialVersionUID = 0; - } - - - private void readObject(ObjectInputStream stream) - throws InvalidObjectException { - throw new InvalidObjectException("Use SerializedForm"); - } - - - @Override Object writeReplace() { - return new SerializedForm(delegateCollection()); - } -} diff --git a/java/src/game/collect/ImmutableCollection.java b/java/src/game/collect/ImmutableCollection.java deleted file mode 100644 index f8e4278..0000000 --- a/java/src/game/collect/ImmutableCollection.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkNonnegative; -import static game.collect.ObjectArrays.checkElementsNotNull; -import static game.collect.Preconditions.checkNotNull; - -import java.io.Serializable; -import java.util.AbstractCollection; -import java.util.Collection; -import java.util.Iterator; - -/** - * An immutable collection. Does not permit null elements. - * - *

In addition to the {@link Collection} methods, this class has an {@link - * #asList()} method, which returns a list view of the collection's elements. - * - *

Note: Although this class is not final, it cannot be subclassed - * outside of this package as it has no public or protected constructors. Thus, - * instances of this type are guaranteed to be immutable. - * - * @author Jesse Wilson - * @since 2.0 (imported from Google Collections Library) - */ - - // we're overriding default serialization -abstract class ImmutableCollection extends AbstractCollection - implements Serializable { - - ImmutableCollection() {} - - /** - * Returns an unmodifiable iterator across the elements in this collection. - */ - @Override - public abstract UnmodifiableIterator iterator(); - - @Override - public final Object[] toArray() { - int size = size(); - if (size == 0) { - return ObjectArrays.EMPTY_ARRAY; - } - Object[] result = new Object[size()]; - copyIntoArray(result, 0); - return result; - } - - @Override - public final T[] toArray(T[] other) { - checkNotNull(other); - int size = size(); - if (other.length < size) { - other = ObjectArrays.newArray(other, size); - } else if (other.length > size) { - other[size] = null; - } - copyIntoArray(other, 0); - return other; - } - - @Override - public boolean contains(Object object) { - return object != null && super.contains(object); - } - - /** - * Guaranteed to throw an exception and leave the collection unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final boolean add(E e) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the collection unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final boolean remove(Object object) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the collection unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final boolean addAll(Collection newElements) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the collection unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final boolean removeAll(Collection oldElements) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the collection unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final boolean retainAll(Collection elementsToKeep) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the collection unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final void clear() { - throw new UnsupportedOperationException(); - } - - /* - * TODO(kevinb): Restructure code so ImmutableList doesn't contain this - * variable, which it doesn't use. - */ - private transient ImmutableList asList; - - /** - * Returns a list view of the collection. - * - * @since 2.0 - */ - public ImmutableList asList() { - ImmutableList list = asList; - return (list == null) ? (asList = createAsList()) : list; - } - - ImmutableList createAsList() { - switch (size()) { - case 0: - return ImmutableList.of(); -// case 1: -// return ImmutableList.of(iterator().next()); - default: - return new RegularImmutableAsList(this, toArray()); - } - } - - /** - * Returns {@code true} if this immutable collection's implementation contains references to - * user-created objects that aren't accessible via this collection's methods. This is generally - * used to determine whether {@code copyOf} implementations should make an explicit copy to avoid - * memory leaks. - */ - abstract boolean isPartialView(); - - /** - * Copies the contents of this immutable collection into the specified array at the specified - * offset. Returns {@code offset + size()}. - */ - int copyIntoArray(Object[] dst, int offset) { - for (E e : this) { - dst[offset++] = e; - } - return offset; - } - - Object writeReplace() { - // We serialize by default to ImmutableList, the simplest thing that works. - return new ImmutableList.SerializedForm(toArray()); - } - - /** - * Abstract base class for builders of {@link ImmutableCollection} types. - * - * @since 10.0 - */ - public abstract static class Builder { - static final int DEFAULT_INITIAL_CAPACITY = 4; - - static int expandedCapacity(int oldCapacity, int minCapacity) { - if (minCapacity < 0) { - throw new AssertionError("cannot store more than MAX_VALUE elements"); - } - // careful of overflow! - int newCapacity = oldCapacity + (oldCapacity >> 1) + 1; - if (newCapacity < minCapacity) { - newCapacity = Integer.highestOneBit(minCapacity - 1) << 1; - } - if (newCapacity < 0) { - newCapacity = Integer.MAX_VALUE; - // guaranteed to be >= newCapacity - } - return newCapacity; - } - - Builder() { - } - - /** - * Adds {@code element} to the {@code ImmutableCollection} being built. - * - *

Note that each builder class covariantly returns its own type from - * this method. - * - * @param element the element to add - * @return this {@code Builder} instance - * @throws NullPointerException if {@code element} is null - */ - public abstract Builder add(E element); - - /** - * Adds each element of {@code elements} to the {@code ImmutableCollection} - * being built. - * - *

Note that each builder class overrides this method in order to - * covariantly return its own type. - * - * @param elements the elements to add - * @return this {@code Builder} instance - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - public Builder add(E... elements) { - for (E element : elements) { - add(element); - } - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableCollection} - * being built. - * - *

Note that each builder class overrides this method in order to - * covariantly return its own type. - * - * @param elements the elements to add - * @return this {@code Builder} instance - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - public Builder addAll(Iterable elements) { - for (E element : elements) { - add(element); - } - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableCollection} - * being built. - * - *

Note that each builder class overrides this method in order to - * covariantly return its own type. - * - * @param elements the elements to add - * @return this {@code Builder} instance - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - public Builder addAll(Iterator elements) { - while (elements.hasNext()) { - add(elements.next()); - } - return this; - } - - /** - * Returns a newly-created {@code ImmutableCollection} of the appropriate - * type, containing the elements provided to this builder. - * - *

Note that each builder class covariantly returns the appropriate type - * of {@code ImmutableCollection} from this method. - */ - public abstract ImmutableCollection build(); - } - - abstract static class ArrayBasedBuilder extends ImmutableCollection.Builder { - Object[] contents; - int size; - - ArrayBasedBuilder(int initialCapacity) { - checkNonnegative(initialCapacity, "initialCapacity"); - this.contents = new Object[initialCapacity]; - this.size = 0; - } - - /** - * Expand the absolute capacity of the builder so it can accept at least - * the specified number of elements without being resized. - */ - private void ensureCapacity(int minCapacity) { - if (contents.length < minCapacity) { - this.contents = ObjectArrays.arraysCopyOf( - this.contents, expandedCapacity(contents.length, minCapacity)); - } - } - - @Override - public ArrayBasedBuilder add(E element) { - checkNotNull(element); - ensureCapacity(size + 1); - contents[size++] = element; - return this; - } - - @Override - public Builder add(E... elements) { - checkElementsNotNull(elements); - ensureCapacity(size + elements.length); - System.arraycopy(elements, 0, contents, size, elements.length); - size += elements.length; - return this; - } - - @Override - public Builder addAll(Iterable elements) { - if (elements instanceof Collection) { - Collection collection = (Collection) elements; - ensureCapacity(size + collection.size()); - } - super.addAll(elements); - return this; - } - } -} diff --git a/java/src/game/collect/ImmutableEntry.java b/java/src/game/collect/ImmutableEntry.java deleted file mode 100644 index 7be0652..0000000 --- a/java/src/game/collect/ImmutableEntry.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.io.Serializable; - -/** - * @see com.google.common.collect.Maps#immutableEntry(Object, Object) - */ - -class ImmutableEntry extends AbstractMapEntry - implements Serializable { - final K key; - final V value; - - ImmutableEntry(K key, V value) { - this.key = key; - this.value = value; - } - - @Override public final K getKey() { - return key; - } - - @Override public final V getValue() { - return value; - } - - @Override public final V setValue(V value) { - throw new UnsupportedOperationException(); - } - - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/collect/ImmutableEnumMap.java b/java/src/game/collect/ImmutableEnumMap.java deleted file mode 100644 index 163cf97..0000000 --- a/java/src/game/collect/ImmutableEnumMap.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package game.collect; - -import static game.collect.Preconditions.checkArgument; - -import java.util.EnumMap; -import java.util.Iterator; - -/** - * Implementation of {@link ImmutableMap} backed by a non-empty {@link - * java.util.EnumMap}. - * - * @author Louis Wasserman - */ - - // we're overriding default serialization -final class ImmutableEnumMap, V> extends ImmutableMap { - static , V> ImmutableMap asImmutable(EnumMap map) { - switch (map.size()) { - case 0: - return ImmutableMap.of(); -// case 1: { -// Entry entry = Iterables.getOnlyElement(map.entrySet()); -// return ImmutableMap.of(entry.getKey(), entry.getValue()); -// } - default: - return new ImmutableEnumMap(map); - } - } - - private transient final EnumMap delegate; - - private ImmutableEnumMap(EnumMap delegate) { - this.delegate = delegate; - checkArgument(!delegate.isEmpty()); - } - - @Override - ImmutableSet createKeySet() { - return new ImmutableSet() { - - @Override - public boolean contains(Object object) { - return delegate.containsKey(object); - } - - @Override - public int size() { - return ImmutableEnumMap.this.size(); - } - - @Override - public UnmodifiableIterator iterator() { - return Iterators.unmodifiableIterator(delegate.keySet().iterator()); - } - - @Override - boolean isPartialView() { - return true; - } - }; - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public boolean containsKey(Object key) { - return delegate.containsKey(key); - } - - @Override - public V get(Object key) { - return delegate.get(key); - } - - @Override - ImmutableSet> createEntrySet() { - return new ImmutableMapEntrySet() { - - @Override - ImmutableMap map() { - return ImmutableEnumMap.this; - } - - @Override - public UnmodifiableIterator> iterator() { - return new UnmodifiableIterator>() { - private final Iterator> backingIterator = delegate.entrySet().iterator(); - - @Override - public boolean hasNext() { - return backingIterator.hasNext(); - } - - @Override - public Entry next() { - Entry entry = backingIterator.next(); - return Maps.immutableEntry(entry.getKey(), entry.getValue()); - } - }; - } - }; - } - - @Override - boolean isPartialView() { - return false; - } - - // All callers of the constructor are restricted to >. -// @Override Object writeReplace() { -// return new EnumSerializedForm(delegate); -// } -// -// /* -// * This class is used to serialize ImmutableEnumSet instances. -// */ -// private static class EnumSerializedForm, V> -// implements Serializable { -// final EnumMap delegate; -// EnumSerializedForm(EnumMap delegate) { -// this.delegate = delegate; -// } -// Object readResolve() { -// return new ImmutableEnumMap(delegate); -// } -// private static final long serialVersionUID = 0; -// } -} diff --git a/java/src/game/collect/ImmutableEnumSet.java b/java/src/game/collect/ImmutableEnumSet.java deleted file mode 100644 index 8f49f32..0000000 --- a/java/src/game/collect/ImmutableEnumSet.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.io.Serializable; -import java.util.Collection; -import java.util.EnumSet; - -/** - * Implementation of {@link ImmutableSet} backed by a non-empty {@link - * java.util.EnumSet}. - * - * @author Jared Levy - */ - - // we're overriding default serialization -final class ImmutableEnumSet> extends ImmutableSet { - static > ImmutableSet asImmutable(EnumSet set) { - switch (set.size()) { - case 0: - return ImmutableSet.of(); -// case 1: -// return ImmutableSet.of(Iterables.getOnlyElement(set)); - default: - return new ImmutableEnumSet(set); - } - } - - /* - * Notes on EnumSet and >: - * - * This class isn't an arbitrary ForwardingImmutableSet because we need to - * know that calling {@code clone()} during deserialization will return an - * object that no one else has a reference to, allowing us to guarantee - * immutability. Hence, we support only {@link EnumSet}. - */ - private final transient EnumSet delegate; - - private ImmutableEnumSet(EnumSet delegate) { - this.delegate = delegate; - } - - @Override boolean isPartialView() { - return false; - } - - @Override public UnmodifiableIterator iterator() { - return Iterators.unmodifiableIterator(delegate.iterator()); - } - - @Override - public int size() { - return delegate.size(); - } - - @Override public boolean contains(Object object) { - return delegate.contains(object); - } - - @Override public boolean containsAll(Collection collection) { - return delegate.containsAll(collection); - } - - @Override public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override public boolean equals(Object object) { - return object == this || delegate.equals(object); - } - - private transient int hashCode; - - @Override public int hashCode() { - int result = hashCode; - return (result == 0) ? hashCode = delegate.hashCode() : result; - } - - @Override public String toString() { - return delegate.toString(); - } - - // All callers of the constructor are restricted to >. - @Override Object writeReplace() { - return new EnumSerializedForm(delegate); - } - - /* - * This class is used to serialize ImmutableEnumSet instances. - */ - private static class EnumSerializedForm> - implements Serializable { - final EnumSet delegate; - EnumSerializedForm(EnumSet delegate) { - this.delegate = delegate; - } - Object readResolve() { - // EJ2 #76: Write readObject() methods defensively. - return new ImmutableEnumSet(delegate.clone()); - } - private static final long serialVersionUID = 0; - } -} diff --git a/java/src/game/collect/ImmutableList.java b/java/src/game/collect/ImmutableList.java deleted file mode 100644 index 17f8b27..0000000 --- a/java/src/game/collect/ImmutableList.java +++ /dev/null @@ -1,743 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.ObjectArrays.arraysCopyOf; -import static game.collect.ObjectArrays.checkElementsNotNull; -import static game.collect.Preconditions.checkElementIndex; -import static game.collect.Preconditions.checkNotNull; -import static game.collect.Preconditions.checkPositionIndexes; - -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.RandomAccess; - -/** - * A high-performance, immutable, random-access {@code List} implementation. - * Does not permit null elements. - * - *

Unlike {@link Collections#unmodifiableList}, which is a view of a - * separate collection that can still change, an instance of {@code - * ImmutableList} contains its own private data and will never change. - * {@code ImmutableList} is convenient for {@code public static final} lists - * ("constant lists") and also lets you easily make a "defensive copy" of a list - * provided to your class by a caller. - * - *

Note: Although this class is not final, it cannot be subclassed as - * it has no public or protected constructors. Thus, instances of this type are - * guaranteed to be immutable. - * - *

See the Guava User Guide article on - * immutable collections. - * - * @see ImmutableMap - * @see ImmutableSet - * @author Kevin Bourrillion - * @since 2.0 (imported from Google Collections Library) - */ - - // we're overriding default serialization -public abstract class ImmutableList extends ImmutableCollection - implements List, RandomAccess { - - private static final ImmutableList EMPTY = - new RegularImmutableList(ObjectArrays.EMPTY_ARRAY); - - /** - * Returns the empty immutable list. This set behaves and performs comparably - * to {@link Collections#emptyList}, and is preferable mainly for consistency - * and maintainability of your code. - */ - // Casting to any type is safe because the list will never hold any elements. - - public static ImmutableList of() { - return (ImmutableList) EMPTY; - } - - /** - * Returns an immutable list containing a single element. This list behaves - * and performs comparably to {@link Collections#singleton}, but will not - * accept a null element. It is preferable mainly for consistency and - * maintainability of your code. - * - * @throws NullPointerException if {@code element} is null - */ -// public static ImmutableList of(E element) { -// return new SingletonImmutableList(element); -// } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of(E e1, E e2) { - return construct(e1, e2); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of(E e1, E e2, E e3) { - return construct(e1, e2, e3); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of(E e1, E e2, E e3, E e4) { - return construct(e1, e2, e3, e4); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of(E e1, E e2, E e3, E e4, E e5) { - return construct(e1, e2, e3, e4, e5); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6) { - return construct(e1, e2, e3, e4, e5, e6); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of( - E e1, E e2, E e3, E e4, E e5, E e6, E e7) { - return construct(e1, e2, e3, e4, e5, e6, e7); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of( - E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { - return construct(e1, e2, e3, e4, e5, e6, e7, e8); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of( - E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { - return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of( - E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { - return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableList of( - E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) { - return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11); - } - - // These go up to eleven. After that, you just get the varargs form, and - // whatever warnings might come along with it. :( - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any element is null - * @since 3.0 (source-compatible since 2.0) - */ - public static ImmutableList of( - E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, - E... others) { - Object[] array = new Object[12 + others.length]; - array[0] = e1; - array[1] = e2; - array[2] = e3; - array[3] = e4; - array[4] = e5; - array[5] = e6; - array[6] = e7; - array[7] = e8; - array[8] = e9; - array[9] = e10; - array[10] = e11; - array[11] = e12; - System.arraycopy(others, 0, array, 12, others.length); - return construct(array); - } - - /** - * Returns an immutable list containing the given elements, in order. If - * {@code elements} is a {@link Collection}, this method behaves exactly as - * {@link #copyOf(Collection)}; otherwise, it behaves exactly as {@code - * copyOf(elements.iterator()}. - * - * @throws NullPointerException if any of {@code elements} is null - */ - public static ImmutableList copyOf(Iterable elements) { - checkNotNull(elements); // TODO(kevinb): is this here only for GWT? - return (elements instanceof Collection) - ? copyOf(Filter.cast(elements)) - : copyOf(elements.iterator()); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - *

Despite the method name, this method attempts to avoid actually copying - * the data when it is safe to do so. The exact circumstances under which a - * copy will or will not be performed are undocumented and subject to change. - * - *

Note that if {@code list} is a {@code List}, then {@code - * ImmutableList.copyOf(list)} returns an {@code ImmutableList} - * containing each of the strings in {@code list}, while - * ImmutableList.of(list)} returns an {@code ImmutableList>} - * containing one element (the given list itself). - * - *

This method is safe to use even when {@code elements} is a synchronized - * or concurrent collection that is currently being modified by another - * thread. - * - * @throws NullPointerException if any of {@code elements} is null - */ - public static ImmutableList copyOf(Collection elements) { - if (elements instanceof ImmutableCollection) { - // all supported methods are covariant - ImmutableList list = ((ImmutableCollection) elements).asList(); - return list.isPartialView() - ? ImmutableList.asImmutableList(list.toArray()) - : list; - } - return construct(elements.toArray()); - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any of {@code elements} is null - */ - public static ImmutableList copyOf(Iterator elements) { - // We special-case for 0 or 1 elements, but going further is madness. - if (!elements.hasNext()) { - return of(); - } -// E first = elements.next(); -// if (!elements.hasNext()) { -// return of(first); -// } else { - return new ImmutableList.Builder() -// .add(first) - .addAll(elements) - .build(); -// } - } - - /** - * Returns an immutable list containing the given elements, in order. - * - * @throws NullPointerException if any of {@code elements} is null - * @since 3.0 - */ - public static ImmutableList copyOf(E[] elements) { - switch (elements.length) { - case 0: - return ImmutableList.of(); -// case 1: -// return new SingletonImmutableList(elements[0]); - default: - return new RegularImmutableList(checkElementsNotNull(elements.clone())); - } - } - - /** - * Views the array as an immutable list. Checks for nulls; does not copy. - */ - private static ImmutableList construct(Object... elements) { - return asImmutableList(checkElementsNotNull(elements)); - } - - /** - * Views the array as an immutable list. Does not check for nulls; does not copy. - * - *

The array must be internally created. - */ - static ImmutableList asImmutableList(Object[] elements) { - return asImmutableList(elements, elements.length); - } - - /** - * Views the array as an immutable list. Copies if the specified range does not cover the complete - * array. Does not check for nulls. - */ - static ImmutableList asImmutableList(Object[] elements, int length) { - switch (length) { - case 0: - return of(); -// case 1: -// // collection had only Es in it -// ImmutableList list = new SingletonImmutableList((E) elements[0]); -// return list; - default: - if (length < elements.length) { - elements = arraysCopyOf(elements, length); - } - return new RegularImmutableList(elements); - } - } - - ImmutableList() {} - - // This declaration is needed to make List.iterator() and - // ImmutableCollection.iterator() consistent. - @Override public UnmodifiableIterator iterator() { - return listIterator(); - } - - @Override public UnmodifiableListIterator listIterator() { - return listIterator(0); - } - - @Override public UnmodifiableListIterator listIterator(int index) { - return new AbstractIndexedListIterator(size(), index) { - @Override - protected E get(int index) { - return ImmutableList.this.get(index); - } - }; - } - - @Override - public int indexOf(Object object) { - return (object == null) ? -1 : indexOfImpl(this, object); - } - - @Override - public int lastIndexOf(Object object) { - return (object == null) ? -1 : lastIndexOfImpl(this, object); - } - - @Override - public boolean contains(Object object) { - return indexOf(object) >= 0; - } - - // constrain the return type to ImmutableList - - /** - * Returns an immutable list of the elements between the specified {@code - * fromIndex}, inclusive, and {@code toIndex}, exclusive. (If {@code - * fromIndex} and {@code toIndex} are equal, the empty immutable list is - * returned.) - */ - @Override - public ImmutableList subList(int fromIndex, int toIndex) { - checkPositionIndexes(fromIndex, toIndex, size()); - int length = toIndex - fromIndex; - switch (length) { - case 0: - return of(); -// case 1: -// return of(get(fromIndex)); - default: - return subListUnchecked(fromIndex, toIndex); - } - } - - /** - * Called by the default implementation of {@link #subList} when {@code - * toIndex - fromIndex > 1}, after index validation has already been - * performed. - */ - ImmutableList subListUnchecked(int fromIndex, int toIndex) { - return new SubList(fromIndex, toIndex - fromIndex); - } - - class SubList extends ImmutableList { - transient final int offset; - transient final int length; - - SubList(int offset, int length) { - this.offset = offset; - this.length = length; - } - - @Override - public int size() { - return length; - } - - @Override - public E get(int index) { - checkElementIndex(index, length); - return ImmutableList.this.get(index + offset); - } - - @Override - public ImmutableList subList(int fromIndex, int toIndex) { - checkPositionIndexes(fromIndex, toIndex, length); - return ImmutableList.this.subList(fromIndex + offset, toIndex + offset); - } - - @Override - boolean isPartialView() { - return true; - } - } - - /** - * Guaranteed to throw an exception and leave the list unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final boolean addAll(int index, Collection newElements) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the list unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final E set(int index, E element) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the list unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final void add(int index, E element) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the list unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final E remove(int index) { - throw new UnsupportedOperationException(); - } - - /** - * Returns this list instance. - * - * @since 2.0 - */ - @Override public final ImmutableList asList() { - return this; - } - - @Override - int copyIntoArray(Object[] dst, int offset) { - // this loop is faster for RandomAccess instances, which ImmutableLists are - int size = size(); - for (int i = 0; i < size; i++) { - dst[offset + i] = get(i); - } - return offset + size; - } - - /** - * Returns a view of this immutable list in reverse order. For example, {@code - * ImmutableList.of(1, 2, 3).reverse()} is equivalent to {@code - * ImmutableList.of(3, 2, 1)}. - * - * @return a view of this immutable list in reverse order - * @since 7.0 - */ - public ImmutableList reverse() { - return new ReverseImmutableList(this); - } - - private static class ReverseImmutableList extends ImmutableList { - private final transient ImmutableList forwardList; - - ReverseImmutableList(ImmutableList backingList) { - this.forwardList = backingList; - } - - private int reverseIndex(int index) { - return (size() - 1) - index; - } - - private int reversePosition(int index) { - return size() - index; - } - - @Override public ImmutableList reverse() { - return forwardList; - } - - @Override public boolean contains(Object object) { - return forwardList.contains(object); - } - - @Override public int indexOf(Object object) { - int index = forwardList.lastIndexOf(object); - return (index >= 0) ? reverseIndex(index) : -1; - } - - @Override public int lastIndexOf(Object object) { - int index = forwardList.indexOf(object); - return (index >= 0) ? reverseIndex(index) : -1; - } - - @Override public ImmutableList subList(int fromIndex, int toIndex) { - checkPositionIndexes(fromIndex, toIndex, size()); - return forwardList.subList( - reversePosition(toIndex), reversePosition(fromIndex)).reverse(); - } - - @Override public E get(int index) { - checkElementIndex(index, size()); - return forwardList.get(reverseIndex(index)); - } - - @Override public int size() { - return forwardList.size(); - } - - @Override boolean isPartialView() { - return forwardList.isPartialView(); - } - } - - /** - * An implementation of {@link List#equals(Object)}. - */ - static boolean equalsImpl(List list, Object object) { - if (object == checkNotNull(list)) { - return true; - } - if (!(object instanceof List)) { - return false; - } - - List o = (List) object; - - return list.size() == o.size() - && Iterators.elementsEqual(list.iterator(), o.iterator()); - } - - /** - * An implementation of {@link List#indexOf(Object)}. - */ - static int indexOfImpl(List list, Object element) { - ListIterator listIterator = list.listIterator(); - while (listIterator.hasNext()) { - if (Preconditions.equal(element, listIterator.next())) { - return listIterator.previousIndex(); - } - } - return -1; - } - - /** - * An implementation of {@link List#lastIndexOf(Object)}. - */ - static int lastIndexOfImpl(List list, Object element) { - ListIterator listIterator = list.listIterator(list.size()); - while (listIterator.hasPrevious()) { - if (Preconditions.equal(element, listIterator.previous())) { - return listIterator.nextIndex(); - } - } - return -1; - } - - @Override public boolean equals(Object obj) { - return equalsImpl(this, obj); - } - - @Override public int hashCode() { - int hashCode = 1; - int n = size(); - for (int i = 0; i < n; i++) { - hashCode = 31 * hashCode + get(i).hashCode(); - - hashCode = ~~hashCode; - // needed to deal with GWT integer overflow - } - return hashCode; - } - - /* - * Serializes ImmutableLists as their logical contents. This ensures that - * implementation types do not leak into the serialized representation. - */ - static class SerializedForm implements Serializable { - final Object[] elements; - SerializedForm(Object[] elements) { - this.elements = elements; - } - Object readResolve() { - return copyOf(elements); - } - private static final long serialVersionUID = 0; - } - - private void readObject(ObjectInputStream stream) - throws InvalidObjectException { - throw new InvalidObjectException("Use SerializedForm"); - } - - @Override Object writeReplace() { - return new SerializedForm(toArray()); - } - - /** - * Returns a new builder. The generated builder is equivalent to the builder - * created by the {@link Builder} constructor. - */ - public static Builder builder() { - return new Builder(); - } - - /** - * A builder for creating immutable list instances, especially {@code public - * static final} lists ("constant lists"). Example:

   {@code
-   *
-   *   public static final ImmutableList GOOGLE_COLORS
-   *       = new ImmutableList.Builder()
-   *           .addAll(WEBSAFE_COLORS)
-   *           .add(new Color(0, 191, 255))
-   *           .build();}
- * - *

Builder instances can be reused; it is safe to call {@link #build} multiple - * times to build multiple lists in series. Each new list contains all the - * elements of the ones created before it. - * - * @since 2.0 (imported from Google Collections Library) - */ - public static final class Builder extends ImmutableCollection.ArrayBasedBuilder { - /** - * Creates a new builder. The returned builder is equivalent to the builder - * generated by {@link ImmutableList#builder}. - */ - public Builder() { - this(DEFAULT_INITIAL_CAPACITY); - } - - // TODO(user): consider exposing this - Builder(int capacity) { - super(capacity); - } - - /** - * Adds {@code element} to the {@code ImmutableList}. - * - * @param element the element to add - * @return this {@code Builder} object - * @throws NullPointerException if {@code element} is null - */ - @Override public Builder add(E element) { - super.add(element); - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableList}. - * - * @param elements the {@code Iterable} to add to the {@code ImmutableList} - * @return this {@code Builder} object - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - @Override public Builder addAll(Iterable elements) { - super.addAll(elements); - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableList}. - * - * @param elements the {@code Iterable} to add to the {@code ImmutableList} - * @return this {@code Builder} object - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - @Override public Builder add(E... elements) { - super.add(elements); - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableList}. - * - * @param elements the {@code Iterable} to add to the {@code ImmutableList} - * @return this {@code Builder} object - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - @Override public Builder addAll(Iterator elements) { - super.addAll(elements); - return this; - } - - /** - * Returns a newly-created {@code ImmutableList} based on the contents of - * the {@code Builder}. - */ - @Override public ImmutableList build() { - return asImmutableList(contents, size); - } - } -} diff --git a/java/src/game/collect/ImmutableMap.java b/java/src/game/collect/ImmutableMap.java deleted file mode 100644 index 4afd22a..0000000 --- a/java/src/game/collect/ImmutableMap.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkEntryNotNull; - -import java.io.Serializable; -import java.util.EnumMap; -import java.util.Map; - -import game.collect.ImmutableMapEntry.TerminalEntry; - -/** - * An immutable, hash-based {@link Map} with reliable user-specified iteration - * order. Does not permit null keys or values. - * - *

Unlike {@link Collections#unmodifiableMap}, which is a view of a - * separate map which can still change, an instance of {@code ImmutableMap} - * contains its own data and will never change. {@code ImmutableMap} is - * convenient for {@code public static final} maps ("constant maps") and also - * lets you easily make a "defensive copy" of a map provided to your class by a - * caller. - * - *

Performance notes: unlike {@link HashMap}, {@code ImmutableMap} is - * not optimized for element types that have slow {@link Object#equals} or - * {@link Object#hashCode} implementations. You can get better performance by - * having your element type cache its own hash codes, and by making use of the - * cached values to short-circuit a slow {@code equals} algorithm. - * - *

See the Guava User Guide article on - * immutable collections. - * - * @author Jesse Wilson - * @author Kevin Bourrillion - * @since 2.0 (imported from Google Collections Library) - */ - -// // we're overriding default serialization -public abstract class ImmutableMap implements Map, Serializable { - - /** - * Returns the empty map. This map behaves and performs comparably to - * {@link Collections#emptyMap}, and is preferable mainly for consistency - * and maintainability of your code. - */ - public static ImmutableMap of() { - return (ImmutableMap)EmptyImmutableMap.INSTANCE; - } - - /** - * Returns an immutable map containing a single entry. This map behaves and - * performs comparably to {@link Collections#singletonMap} but will not accept - * a null key or value. It is preferable mainly for consistency and - * maintainability of your code. - */ -// public static ImmutableMap of(K k1, V v1) { -// return ImmutableBiMap.of(k1, v1); -// } - - /** - * Returns an immutable map containing the given entries, in order. - * - * @throws IllegalArgumentException if duplicate keys are provided - */ - public static ImmutableMap of(K k1, V v1, K k2, V v2) { - return new RegularImmutableMap(entryOf(k1, v1), entryOf(k2, v2)); - } - - /** - * Returns an immutable map containing the given entries, in order. - * - * @throws IllegalArgumentException if duplicate keys are provided - */ - public static ImmutableMap of( - K k1, V v1, K k2, V v2, K k3, V v3) { - return new RegularImmutableMap( - entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)); - } - - /** - * Returns an immutable map containing the given entries, in order. - * - * @throws IllegalArgumentException if duplicate keys are provided - */ - public static ImmutableMap of( - K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { - return new RegularImmutableMap( - entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4)); - } - - /** - * Returns an immutable map containing the given entries, in order. - * - * @throws IllegalArgumentException if duplicate keys are provided - */ - public static ImmutableMap of( - K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { - return new RegularImmutableMap(entryOf(k1, v1), - entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5)); - } - - // looking for of() with > 5 entries? Use the builder instead. - - /** - * Verifies that {@code key} and {@code value} are non-null, and returns a new - * immutable entry with those values. - * - *

A call to {@link Map.Entry#setValue} on the returned entry will always - * throw {@link UnsupportedOperationException}. - */ - static TerminalEntry entryOf(K key, V value) { - checkEntryNotNull(key, value); - return new TerminalEntry(key, value); - } - - /** - * Returns a new builder. The generated builder is equivalent to the builder - * created by the {@link Builder} constructor. - */ - public static Builder builder() { - return new Builder(); - } - - static void checkNoConflict(boolean safe, String conflictDescription, - Entry entry1, Entry entry2) { - if (!safe) { - throw new IllegalArgumentException( - "Multiple entries with same " + conflictDescription + ": " + entry1 + " and " + entry2); - } - } - - /** - * A builder for creating immutable map instances, especially {@code public - * static final} maps ("constant maps"). Example:

   {@code
-   *
-   *   static final ImmutableMap WORD_TO_INT =
-   *       new ImmutableMap.Builder()
-   *           .put("one", 1)
-   *           .put("two", 2)
-   *           .put("three", 3)
-   *           .build();}
- * - *

For small immutable maps, the {@code ImmutableMap.of()} methods are - * even more convenient. - * - *

Builder instances can be reused - it is safe to call {@link #build} - * multiple times to build multiple maps in series. Each map is a superset of - * the maps created before it. - * - * @since 2.0 (imported from Google Collections Library) - */ - public static class Builder { - TerminalEntry[] entries; - int size; - - /** - * Creates a new builder. The returned builder is equivalent to the builder - * generated by {@link ImmutableMap#builder}. - */ - public Builder() { - this(ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY); - } - - - Builder(int initialCapacity) { - this.entries = new TerminalEntry[initialCapacity]; - this.size = 0; - } - - private void ensureCapacity(int minCapacity) { - if (minCapacity > entries.length) { - entries = ObjectArrays.arraysCopyOf( - entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity)); - } - } - - /** - * Associates {@code key} with {@code value} in the built map. Duplicate - * keys are not allowed, and will cause {@link #build} to fail. - */ - public Builder put(K key, V value) { - ensureCapacity(size + 1); - TerminalEntry entry = entryOf(key, value); - // don't inline this: we want to fail atomically if key or value is null - entries[size++] = entry; - return this; - } - - /** - * Adds the given {@code entry} to the map, making it immutable if - * necessary. Duplicate keys are not allowed, and will cause {@link #build} - * to fail. - * - * @since 11.0 - */ - public Builder put(Entry entry) { - return put(entry.getKey(), entry.getValue()); - } - - /** - * Associates all of the given map's keys and values in the built map. - * Duplicate keys are not allowed, and will cause {@link #build} to fail. - * - * @throws NullPointerException if any key or value in {@code map} is null - */ - public Builder putAll(Map map) { - ensureCapacity(size + map.size()); - for (Entry entry : map.entrySet()) { - put(entry); - } - return this; - } - - /* - * TODO(kevinb): Should build() and the ImmutableBiMap & ImmutableSortedMap - * versions throw an IllegalStateException instead? - */ - - /** - * Returns a newly-created immutable map. - * - * @throws IllegalArgumentException if duplicate keys were added - */ - public ImmutableMap build() { - switch (size) { - case 0: - return of(); -// case 1: -// return of(entries[0].getKey(), entries[0].getValue()); - default: - return new RegularImmutableMap(size, entries); - } - } - } - - /** - * Returns an immutable map containing the same entries as {@code map}. If - * {@code map} somehow contains entries with duplicate keys (for example, if - * it is a {@code SortedMap} whose comparator is not consistent with - * equals), the results of this method are undefined. - * - *

Despite the method name, this method attempts to avoid actually copying - * the data when it is safe to do so. The exact circumstances under which a - * copy will or will not be performed are undocumented and subject to change. - * - * @throws NullPointerException if any key or value in {@code map} is null - */ - public static ImmutableMap copyOf( - Map map) { - if ((map instanceof ImmutableMap)) { // && !(map instanceof ImmutableSortedMap)) { - // TODO(user): Make ImmutableMap.copyOf(immutableBiMap) call copyOf() - // on the ImmutableMap delegate(), rather than the bimap itself - - // safe since map is not writable - ImmutableMap kvMap = (ImmutableMap) map; - if (!kvMap.isPartialView()) { - return kvMap; - } - } else if (map instanceof EnumMap) { - return copyOfEnumMapUnsafe(map); - } - Entry[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY); - switch (entries.length) { - case 0: - return of(); -// case 1: -// // all entries will be Entry's -// Entry onlyEntry = (Entry) entries[0]; -// return of(onlyEntry.getKey(), onlyEntry.getValue()); - default: - return new RegularImmutableMap(entries); - } - } - - // If the map is an EnumMap, it must have key type K for some >. - - private static ImmutableMap copyOfEnumMapUnsafe(Map map) { - return copyOfEnumMap((EnumMap) map); - } - - private static , V> ImmutableMap copyOfEnumMap( - Map original) { - EnumMap copy = new EnumMap(original); - for (Map.Entry entry : copy.entrySet()) { - checkEntryNotNull(entry.getKey(), entry.getValue()); - } - return ImmutableEnumMap.asImmutable(copy); - } - - private static final Entry[] EMPTY_ENTRY_ARRAY = new Entry[0]; - - ImmutableMap() {} - - /** - * Guaranteed to throw an exception and leave the map unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final V put(K k, V v) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the map unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final V remove(Object o) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the map unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final void putAll(Map map) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the map unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final void clear() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isEmpty() { - return size() == 0; - } - - @Override - public boolean containsKey(Object key) { - return get(key) != null; - } - - @Override - public boolean containsValue(Object value) { - return values().contains(value); - } - - // Overriding to mark it Nullable - @Override - public abstract V get(Object key); - - private transient ImmutableSet> entrySet; - - /** - * Returns an immutable set of the mappings in this map. The entries are in - * the same order as the parameters used to build this map. - */ - @Override - public ImmutableSet> entrySet() { - ImmutableSet> result = entrySet; - return (result == null) ? entrySet = createEntrySet() : result; - } - - abstract ImmutableSet> createEntrySet(); - - private transient ImmutableSet keySet; - - /** - * Returns an immutable set of the keys in this map. These keys are in - * the same order as the parameters used to build this map. - */ - @Override - public ImmutableSet keySet() { - ImmutableSet result = keySet; - return (result == null) ? keySet = createKeySet() : result; - } - - ImmutableSet createKeySet() { - return new ImmutableMapKeySet(this); - } - - private transient ImmutableCollection values; - - /** - * Returns an immutable collection of the values in this map. The values are - * in the same order as the parameters used to build this map. - */ - @Override - public ImmutableCollection values() { - ImmutableCollection result = values; - return (result == null) ? values = new ImmutableMapValues(this) : result; - } - - // cached so that this.multimapView().inverse() only computes inverse once -// private transient ImmutableSetMultimap multimapView; - - /** - * Returns a multimap view of the map. - * - * @since 14.0 - */ -// @Beta -// public ImmutableSetMultimap asMultimap() { -// ImmutableSetMultimap result = multimapView; -// return (result == null) ? (multimapView = createMultimapView()) : result; -// } -// -// private ImmutableSetMultimap createMultimapView() { -// ImmutableMap> map = viewMapValuesAsSingletonSets(); -// return new ImmutableSetMultimap(map, map.size(), null); -// } - -// private ImmutableMap> viewMapValuesAsSingletonSets() { -// return new MapViewOfValuesAsSingletonSets(this); -// } -// -// private static final class MapViewOfValuesAsSingletonSets -// extends ImmutableMap> { -// private final ImmutableMap delegate; -// -// MapViewOfValuesAsSingletonSets(ImmutableMap delegate) { -// this.delegate = checkNotNull(delegate); -// } -// -// @Override public int size() { -// return delegate.size(); -// } -// -// @Override public boolean containsKey(Object key) { -// return delegate.containsKey(key); -// } -// -// @Override public ImmutableSet get(Object key) { -// V outerValue = delegate.get(key); -// return (outerValue == null) ? null : ImmutableSet.of(outerValue); -// } -// -// @Override boolean isPartialView() { -// return false; -// } -// -// @Override ImmutableSet>> createEntrySet() { -// return new ImmutableMapEntrySet>() { -// @Override ImmutableMap> map() { -// return MapViewOfValuesAsSingletonSets.this; -// } -// -// @Override -// public UnmodifiableIterator>> iterator() { -// final Iterator> backingIterator = delegate.entrySet().iterator(); -// return new UnmodifiableIterator>>() { -// @Override public boolean hasNext() { -// return backingIterator.hasNext(); -// } -// -// @Override public Entry> next() { -// final Entry backingEntry = backingIterator.next(); -// return new AbstractMapEntry>() { -// @Override public K getKey() { -// return backingEntry.getKey(); -// } -// -// @Override public ImmutableSet getValue() { -// return ImmutableSet.of(backingEntry.getValue()); -// } -// }; -// } -// }; -// } -// }; -// } -// } - - @Override public boolean equals(Object object) { - return Maps.equalsImpl(this, object); - } - - abstract boolean isPartialView(); - - @Override public int hashCode() { - // not caching hash code since it could change if map values are mutable - // in a way that modifies their hash codes - return entrySet().hashCode(); - } - -// @Override public String toString() { -// return Maps.toStringImpl(this); -// } - - /** - * Serialized type for all ImmutableMap instances. It captures the logical - * contents and they are reconstructed using public factory methods. This - * ensures that the implementation types remain as implementation details. - */ -// static class SerializedForm implements Serializable { -// private final Object[] keys; -// private final Object[] values; -// SerializedForm(ImmutableMap map) { -// keys = new Object[map.size()]; -// values = new Object[map.size()]; -// int i = 0; -// for (Entry entry : map.entrySet()) { -// keys[i] = entry.getKey(); -// values[i] = entry.getValue(); -// i++; -// } -// } -// Object readResolve() { -// Builder builder = new Builder(); -// return createMap(builder); -// } -// Object createMap(Builder builder) { -// for (int i = 0; i < keys.length; i++) { -// builder.put(keys[i], values[i]); -// } -// return builder.build(); -// } -// private static final long serialVersionUID = 0; -// } -// -// Object writeReplace() { -// return new SerializedForm(this); -// } -} diff --git a/java/src/game/collect/ImmutableMapEntry.java b/java/src/game/collect/ImmutableMapEntry.java deleted file mode 100644 index 4d49e44..0000000 --- a/java/src/game/collect/ImmutableMapEntry.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2013 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkEntryNotNull; - -/** - * Implementation of {@code Map.Entry} for {@link ImmutableMap} that adds extra methods to traverse - * hash buckets for the key and the value. This allows reuse in {@link RegularImmutableMap} and - * {@link RegularImmutableBiMap}, which don't have to recopy the entries created by their - * {@code Builder} implementations. - * - * @author Louis Wasserman - */ - -abstract class ImmutableMapEntry extends ImmutableEntry { - ImmutableMapEntry(K key, V value) { - super(key, value); - checkEntryNotNull(key, value); - } - - ImmutableMapEntry(ImmutableMapEntry contents) { - super(contents.getKey(), contents.getValue()); - // null check would be redundant - } - - - abstract ImmutableMapEntry getNextInKeyBucket(); - - - abstract ImmutableMapEntry getNextInValueBucket(); - - static final class TerminalEntry extends ImmutableMapEntry { - TerminalEntry(ImmutableMapEntry contents) { - super(contents); - } - - TerminalEntry(K key, V value) { - super(key, value); - } - - @Override - - ImmutableMapEntry getNextInKeyBucket() { - return null; - } - - @Override - - ImmutableMapEntry getNextInValueBucket() { - return null; - } - } -} diff --git a/java/src/game/collect/ImmutableMapEntrySet.java b/java/src/game/collect/ImmutableMapEntrySet.java deleted file mode 100644 index 2c5af4b..0000000 --- a/java/src/game/collect/ImmutableMapEntrySet.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.io.Serializable; -import java.util.Map.Entry; - -/** - * {@code entrySet()} implementation for {@link ImmutableMap}. - * - * @author Jesse Wilson - * @author Kevin Bourrillion - */ - -abstract class ImmutableMapEntrySet extends ImmutableSet> { - ImmutableMapEntrySet() {} - - abstract ImmutableMap map(); - - @Override - public int size() { - return map().size(); - } - - @Override - public boolean contains(Object object) { - if (object instanceof Entry) { - Entry entry = (Entry) object; - V value = map().get(entry.getKey()); - return value != null && value.equals(entry.getValue()); - } - return false; - } - - @Override - boolean isPartialView() { - return map().isPartialView(); - } - - - @Override - Object writeReplace() { - return new EntrySetSerializedForm(map()); - } - - - private static class EntrySetSerializedForm implements Serializable { - final ImmutableMap map; - EntrySetSerializedForm(ImmutableMap map) { - this.map = map; - } - Object readResolve() { - return map.entrySet(); - } - private static final long serialVersionUID = 0; - } -} diff --git a/java/src/game/collect/ImmutableMapKeySet.java b/java/src/game/collect/ImmutableMapKeySet.java deleted file mode 100644 index 9e8b1bd..0000000 --- a/java/src/game/collect/ImmutableMapKeySet.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.io.Serializable; -import java.util.Map.Entry; - -/** - * {@code keySet()} implementation for {@link ImmutableMap}. - * - * @author Jesse Wilson - * @author Kevin Bourrillion - */ - -final class ImmutableMapKeySet extends ImmutableSet { - private final ImmutableMap map; - - ImmutableMapKeySet(ImmutableMap map) { - this.map = map; - } - - @Override - public int size() { - return map.size(); - } - - @Override - public UnmodifiableIterator iterator() { - return asList().iterator(); - } - - @Override - public boolean contains(Object object) { - return map.containsKey(object); - } - - @Override - ImmutableList createAsList() { - final ImmutableList> entryList = map.entrySet().asList(); - return new ImmutableAsList() { - - @Override - public K get(int index) { - return entryList.get(index).getKey(); - } - - @Override - ImmutableCollection delegateCollection() { - return ImmutableMapKeySet.this; - } - - }; - } - - @Override - boolean isPartialView() { - return true; - } - - - @Override Object writeReplace() { - return new KeySetSerializedForm(map); - } - - - private static class KeySetSerializedForm implements Serializable { - final ImmutableMap map; - KeySetSerializedForm(ImmutableMap map) { - this.map = map; - } - Object readResolve() { - return map.keySet(); - } - private static final long serialVersionUID = 0; - } -} diff --git a/java/src/game/collect/ImmutableMapValues.java b/java/src/game/collect/ImmutableMapValues.java deleted file mode 100644 index 63b4fa3..0000000 --- a/java/src/game/collect/ImmutableMapValues.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.io.Serializable; -import java.util.Map.Entry; - -/** - * {@code values()} implementation for {@link ImmutableMap}. - * - * @author Jesse Wilson - * @author Kevin Bourrillion - */ - -final class ImmutableMapValues extends ImmutableCollection { - private final ImmutableMap map; - - ImmutableMapValues(ImmutableMap map) { - this.map = map; - } - - @Override - public int size() { - return map.size(); - } - - @Override - public UnmodifiableIterator iterator() { - return Maps.valueIterator(map.entrySet().iterator()); - } - - @Override - public boolean contains(Object object) { - return object != null && Iterators.contains(iterator(), object); - } - - @Override - boolean isPartialView() { - return true; - } - - @Override - ImmutableList createAsList() { - final ImmutableList> entryList = map.entrySet().asList(); - return new ImmutableAsList() { - @Override - public V get(int index) { - return entryList.get(index).getValue(); - } - - @Override - ImmutableCollection delegateCollection() { - return ImmutableMapValues.this; - } - }; - } - - - @Override Object writeReplace() { - return new SerializedForm(map); - } - - - private static class SerializedForm implements Serializable { - final ImmutableMap map; - SerializedForm(ImmutableMap map) { - this.map = map; - } - Object readResolve() { - return map.values(); - } - private static final long serialVersionUID = 0; - } -} diff --git a/java/src/game/collect/ImmutableSet.java b/java/src/game/collect/ImmutableSet.java deleted file mode 100644 index 4903f1a..0000000 --- a/java/src/game/collect/ImmutableSet.java +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.ObjectArrays.checkElementNotNull; -import static game.collect.Preconditions.checkArgument; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.Set; - -/** - * A high-performance, immutable {@code Set} with reliable, user-specified - * iteration order. Does not permit null elements. - * - *

Unlike {@link Collections#unmodifiableSet}, which is a view of a - * separate collection that can still change, an instance of this class contains - * its own private data and will never change. This class is convenient - * for {@code public static final} sets ("constant sets") and also lets you - * easily make a "defensive copy" of a set provided to your class by a caller. - * - *

Warning: Like most sets, an {@code ImmutableSet} will not function - * correctly if an element is modified after being placed in the set. For this - * reason, and to avoid general confusion, it is strongly recommended to place - * only immutable objects into this collection. - * - *

This class has been observed to perform significantly better than {@link - * HashSet} for objects with very fast {@link Object#hashCode} implementations - * (as a well-behaved immutable object should). While this class's factory - * methods create hash-based instances, the {@link ImmutableSortedSet} subclass - * performs binary searches instead. - * - *

Note: Although this class is not final, it cannot be subclassed - * outside its package as it has no public or protected constructors. Thus, - * instances of this type are guaranteed to be immutable. - * - *

See the Guava User Guide article on - * immutable collections. - * - * @see ImmutableList - * @see ImmutableMap - * @author Kevin Bourrillion - * @author Nick Kralevich - * @since 2.0 (imported from Google Collections Library) - */ - - // we're overriding default serialization -public abstract class ImmutableSet extends ImmutableCollection - implements Set { - /** - * Returns the empty immutable set. This set behaves and performs comparably - * to {@link Collections#emptySet}, and is preferable mainly for consistency - * and maintainability of your code. - */ - // Casting to any type is safe because the set will never hold any elements. - - public static ImmutableSet of() { - return (ImmutableSet) EmptyImmutableSet.INSTANCE; - } - - /** - * Returns an immutable set containing a single element. This set behaves and - * performs comparably to {@link Collections#singleton}, but will not accept - * a null element. It is preferable mainly for consistency and - * maintainability of your code. - */ -// public static ImmutableSet of(E element) { -// return new SingletonImmutableSet(element); -// } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableSet of(E e1, E e2) { - return construct(2, e1, e2); - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableSet of(E e1, E e2, E e3) { - return construct(3, e1, e2, e3); - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableSet of(E e1, E e2, E e3, E e4) { - return construct(4, e1, e2, e3, e4); - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. - * - * @throws NullPointerException if any element is null - */ - public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5) { - return construct(5, e1, e2, e3, e4, e5); - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. - * - * @throws NullPointerException if any element is null - * @since 3.0 (source-compatible since 2.0) - */ - public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5, E e6, - E... others) { - final int paramCount = 6; - Object[] elements = new Object[paramCount + others.length]; - elements[0] = e1; - elements[1] = e2; - elements[2] = e3; - elements[3] = e4; - elements[4] = e5; - elements[5] = e6; - System.arraycopy(others, 0, elements, paramCount, others.length); - return construct(elements.length, elements); - } - - /** - * Constructs an {@code ImmutableSet} from the first {@code n} elements of the specified array. - * If {@code k} is the size of the returned {@code ImmutableSet}, then the unique elements of - * {@code elements} will be in the first {@code k} positions, and {@code elements[i] == null} for - * {@code k <= i < n}. - * - *

This may modify {@code elements}. Additionally, if {@code n == elements.length} and - * {@code elements} contains no duplicates, {@code elements} may be used without copying in the - * returned {@code ImmutableSet}, in which case it may no longer be modified. - * - *

{@code elements} may contain only values of type {@code E}. - * - * @throws NullPointerException if any of the first {@code n} elements of {@code elements} is - * null - */ - private static ImmutableSet construct(int n, Object... elements) { - switch (n) { - case 0: - return of(); -// case 1: -// // safe; elements contains only E's -// E elem = (E) elements[0]; -// return of(elem); - default: - // continue below to handle the general case - } - int tableSize = chooseTableSize(n); - Object[] table = new Object[tableSize]; - int mask = tableSize - 1; - int hashCode = 0; - int uniques = 0; - for (int i = 0; i < n; i++) { - Object element = checkElementNotNull(elements[i], i); - int hash = element.hashCode(); - for (int j = Hashing.smear(hash); ; j++) { - int index = j & mask; - Object value = table[index]; - if (value == null) { - // Came to an empty slot. Put the element here. - elements[uniques++] = element; - table[index] = element; - hashCode += hash; - break; - } else if (value.equals(element)) { - break; - } - } - } - Arrays.fill(elements, uniques, n, null); -// if (uniques == 1) { -// // There is only one element or elements are all duplicates -// // we are careful to only pass in E -// E element = (E) elements[0]; -// return new SingletonImmutableSet(element, hashCode); -// } else - if (tableSize != chooseTableSize(uniques)) { - // Resize the table when the array includes too many duplicates. - // when this happens, we have already made a copy - return construct(uniques, elements); - } else { - Object[] uniqueElements = (uniques < elements.length) - ? ObjectArrays.arraysCopyOf(elements, uniques) - : elements; - return new RegularImmutableSet(uniqueElements, hashCode, table, mask); - } - } - - // We use power-of-2 tables, and this is the highest int that's a power of 2 - static final int MAX_TABLE_SIZE = 1 << (Integer.SIZE - 2); - - // Represents how tightly we can pack things, as a maximum. - private static final double DESIRED_LOAD_FACTOR = 0.7; - - // If the set has this many elements, it will "max out" the table size - private static final int CUTOFF = - (int) (MAX_TABLE_SIZE * DESIRED_LOAD_FACTOR); - - /** - * Returns an array size suitable for the backing array of a hash table that - * uses open addressing with linear probing in its implementation. The - * returned size is the smallest power of two that can hold setSize elements - * with the desired load factor. - * - *

Do not call this method with setSize < 2. - */ -// @VisibleForTesting - static int chooseTableSize(int setSize) { - setSize = setSize < 2 ? 2 : setSize; - // Correct the size for open addressing to match desired load factor. - if (setSize < CUTOFF) { - // Round up to the next highest power of 2. - int tableSize = Integer.highestOneBit(setSize - 1) << 1; - while (tableSize * DESIRED_LOAD_FACTOR < setSize) { - tableSize <<= 1; - } - return tableSize; - } - - // The table can't be completely full or we'll get infinite reprobes - checkArgument(setSize < MAX_TABLE_SIZE, "collection too large"); - return MAX_TABLE_SIZE; - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. - * - * @throws NullPointerException if any of {@code elements} is null - * @since 3.0 - */ - public static ImmutableSet copyOf(E[] elements) { - switch (elements.length) { - case 0: - return of(); -// case 1: -// return of(elements[0]); - default: - return construct(elements.length, elements.clone()); - } - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. This method iterates over {@code elements} at most once. - * - *

Note that if {@code s} is a {@code Set}, then {@code - * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet} containing - * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns - * a {@code ImmutableSet>} containing one element (the given set - * itself). - * - *

Despite the method name, this method attempts to avoid actually copying - * the data when it is safe to do so. The exact circumstances under which a - * copy will or will not be performed are undocumented and subject to change. - * - * @throws NullPointerException if any of {@code elements} is null - */ - public static ImmutableSet copyOf(Iterable elements) { - return (elements instanceof Collection) - ? copyOf(Filter.cast(elements)) - : copyOf(elements.iterator()); - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. - * - * @throws NullPointerException if any of {@code elements} is null - */ - public static ImmutableSet copyOf(Iterator elements) { - // We special-case for 0 or 1 elements, but anything further is madness. - if (!elements.hasNext()) { - return of(); - } -// E first = elements.next(); -// if (!elements.hasNext()) { -// return of(first); -// } else { - return new ImmutableSet.Builder() -// .add(first) - .addAll(elements) - .build(); -// } - } - - /** - * Returns an immutable set containing the given elements, in order. Repeated - * occurrences of an element (according to {@link Object#equals}) after the - * first are ignored. This method iterates over {@code elements} at most - * once. - * - *

Note that if {@code s} is a {@code Set}, then {@code - * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet} containing - * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns - * a {@code ImmutableSet>} containing one element (the given set - * itself). - * - *

Note: Despite what the method name suggests, {@code copyOf} will - * return constant-space views, rather than linear-space copies, of some - * inputs known to be immutable. For some other immutable inputs, such as key - * sets of an {@code ImmutableMap}, it still performs a copy in order to avoid - * holding references to the values of the map. The heuristics used in this - * decision are undocumented and subject to change except that: - *

    - *
  • A full copy will be done of any {@code ImmutableSortedSet}.
  • - *
  • {@code ImmutableSet.copyOf()} is idempotent with respect to pointer - * equality.
  • - *
- * - *

This method is safe to use even when {@code elements} is a synchronized - * or concurrent collection that is currently being modified by another - * thread. - * - * @throws NullPointerException if any of {@code elements} is null - * @since 7.0 (source-compatible since 2.0) - */ - public static ImmutableSet copyOf(Collection elements) { - /* - * TODO(user): consider checking for ImmutableAsList here - * TODO(user): consider checking for Multiset here - */ - if (elements instanceof ImmutableSet) { -// && !(elements instanceof ImmutableSortedSet)) { - // all supported methods are covariant - ImmutableSet set = (ImmutableSet) elements; - if (!set.isPartialView()) { - return set; - } - } else if (elements instanceof EnumSet) { - return copyOfEnumSet((EnumSet) elements); - } - Object[] array = elements.toArray(); - return construct(array.length, array); - } - - private static > ImmutableSet copyOfEnumSet( - EnumSet enumSet) { - return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet)); - } - - ImmutableSet() {} - - /** Returns {@code true} if the {@code hashCode()} method runs quickly. */ - boolean isHashCodeFast() { - return false; - } - - @Override public boolean equals(Object object) { - if (object == this) { - return true; - } else if (object instanceof ImmutableSet - && isHashCodeFast() - && ((ImmutableSet) object).isHashCodeFast() - && hashCode() != object.hashCode()) { - return false; - } - return Sets.equalsImpl(this, object); - } - - @Override public int hashCode() { - return Sets.hashCodeImpl(this); - } - - // This declaration is needed to make Set.iterator() and - // ImmutableCollection.iterator() consistent. - @Override public abstract UnmodifiableIterator iterator(); - - /* - * This class is used to serialize all ImmutableSet instances, except for - * ImmutableEnumSet/ImmutableSortedSet, regardless of implementation type. It - * captures their "logical contents" and they are reconstructed using public - * static factories. This is necessary to ensure that the existence of a - * particular implementation type is an implementation detail. - */ - private static class SerializedForm implements Serializable { - final Object[] elements; - SerializedForm(Object[] elements) { - this.elements = elements; - } - Object readResolve() { - return copyOf(elements); - } - private static final long serialVersionUID = 0; - } - - @Override Object writeReplace() { - return new SerializedForm(toArray()); - } - - /** - * Returns a new builder. The generated builder is equivalent to the builder - * created by the {@link Builder} constructor. - */ - public static Builder builder() { - return new Builder(); - } - - /** - * A builder for creating immutable set instances, especially {@code public - * static final} sets ("constant sets"). Example:

   {@code
-   *
-   *   public static final ImmutableSet GOOGLE_COLORS =
-   *       new ImmutableSet.Builder()
-   *           .addAll(WEBSAFE_COLORS)
-   *           .add(new Color(0, 191, 255))
-   *           .build();}
- * - *

Builder instances can be reused; it is safe to call {@link #build} multiple - * times to build multiple sets in series. Each set is a superset of the set - * created before it. - * - * @since 2.0 (imported from Google Collections Library) - */ - public static class Builder extends ImmutableCollection.ArrayBasedBuilder { - - /** - * Creates a new builder. The returned builder is equivalent to the builder - * generated by {@link ImmutableSet#builder}. - */ - public Builder() { - this(DEFAULT_INITIAL_CAPACITY); - } - - Builder(int capacity) { - super(capacity); - } - - /** - * Adds {@code element} to the {@code ImmutableSet}. If the {@code - * ImmutableSet} already contains {@code element}, then {@code add} has no - * effect (only the previously added element is retained). - * - * @param element the element to add - * @return this {@code Builder} object - * @throws NullPointerException if {@code element} is null - */ - @Override public Builder add(E element) { - super.add(element); - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableSet}, - * ignoring duplicate elements (only the first duplicate element is added). - * - * @param elements the elements to add - * @return this {@code Builder} object - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - @Override public Builder add(E... elements) { - super.add(elements); - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableSet}, - * ignoring duplicate elements (only the first duplicate element is added). - * - * @param elements the {@code Iterable} to add to the {@code ImmutableSet} - * @return this {@code Builder} object - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - @Override public Builder addAll(Iterable elements) { - super.addAll(elements); - return this; - } - - /** - * Adds each element of {@code elements} to the {@code ImmutableSet}, - * ignoring duplicate elements (only the first duplicate element is added). - * - * @param elements the elements to add to the {@code ImmutableSet} - * @return this {@code Builder} object - * @throws NullPointerException if {@code elements} is null or contains a - * null element - */ - @Override public Builder addAll(Iterator elements) { - super.addAll(elements); - return this; - } - - /** - * Returns a newly-created {@code ImmutableSet} based on the contents of - * the {@code Builder}. - */ - @Override public ImmutableSet build() { - ImmutableSet result = construct(size, contents); - // construct has the side effect of deduping contents, so we update size - // accordingly. - size = result.size(); - return result; - } - } -} diff --git a/java/src/game/collect/ImmutableTable.java b/java/src/game/collect/ImmutableTable.java deleted file mode 100644 index 9527f39..0000000 --- a/java/src/game/collect/ImmutableTable.java +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkNotNull; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * An immutable {@link Table} with reliable user-specified iteration order. - * Does not permit null keys or values. - * - *

Note: Although this class is not final, it cannot be subclassed as - * it has no public or protected constructors. Thus, instances of this class are - * guaranteed to be immutable. - * - *

See the Guava User Guide article on - * immutable collections. - * - * @author Gregory Kick - * @since 11.0 - */ - -// TODO(gak): make serializable -public abstract class ImmutableTable extends AbstractTable { - private static final ImmutableTable EMPTY - = new SparseImmutableTable( - ImmutableList.>of(), - ImmutableSet.of(), ImmutableSet.of()); - - /** Returns an empty immutable table. */ - - public static ImmutableTable of() { - return (ImmutableTable) EMPTY; - } - -// /** Returns an immutable table containing a single cell. */ -// public static ImmutableTable of(R rowKey, -// C columnKey, V value) { -// return new SingletonImmutableTable(rowKey, columnKey, value); -// } - - /** - * Returns an immutable copy of the provided table. - * - *

The {@link Table#cellSet()} iteration order of the provided table - * determines the iteration ordering of all views in the returned table. Note - * that some views of the original table and the copied table may have - * different iteration orders. For more control over the ordering, create a - * {@link Builder} and call {@link Builder#orderRowsBy}, - * {@link Builder#orderColumnsBy}, and {@link Builder#putAll} - * - *

Despite the method name, this method attempts to avoid actually copying - * the data when it is safe to do so. The exact circumstances under which a - * copy will or will not be performed are undocumented and subject to change. - */ - public static ImmutableTable copyOf( - Table table) { - if (table instanceof ImmutableTable) { - - ImmutableTable parameterizedTable - = (ImmutableTable) table; - return parameterizedTable; - } else { - int size = table.size(); - switch (size) { - case 0: - return of(); -// case 1: -// Cell onlyCell -// = Iterables.getOnlyElement(table.cellSet()); -// return ImmutableTable.of(onlyCell.getRowKey(), -// onlyCell.getColumnKey(), onlyCell.getValue()); - default: - ImmutableSet.Builder> cellSetBuilder - = ImmutableSet.builder(); - for (Cell cell : - table.cellSet()) { - /* - * Must cast to be able to create a Cell rather than a - * Cell - */ - cellSetBuilder.add(cellOf((R) cell.getRowKey(), - (C) cell.getColumnKey(), (V) cell.getValue())); - } - return RegularImmutableTable.forCells(cellSetBuilder.build()); - } - } - } - - /** - * Returns a new builder. The generated builder is equivalent to the builder - * created by the {@link Builder#ImmutableTable.Builder()} constructor. - */ -// public static Builder builder() { -// return new Builder(); -// } - - public static Cell immutableCell( - R rowKey, C columnKey, V value) { - return new ImmutableCell(rowKey, columnKey, value); - } - - static final class ImmutableCell - extends AbstractCell implements Serializable { - private final R rowKey; - private final C columnKey; - private final V value; - - ImmutableCell( - R rowKey, C columnKey, V value) { - this.rowKey = rowKey; - this.columnKey = columnKey; - this.value = value; - } - - @Override - public R getRowKey() { - return rowKey; - } - @Override - public C getColumnKey() { - return columnKey; - } - @Override - public V getValue() { - return value; - } - - private static final long serialVersionUID = 0; - } - - abstract static class AbstractCell implements Cell { - // needed for serialization - AbstractCell() {} - - @Override public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof Cell) { - Cell other = (Cell) obj; - return Preconditions.equal(getRowKey(), other.getRowKey()) - && Preconditions.equal(getColumnKey(), other.getColumnKey()) - && Preconditions.equal(getValue(), other.getValue()); - } - return false; - } - - @Override public int hashCode() { - return Arrays.hashCode(new Object[] {getRowKey(), getColumnKey(), getValue()}); - } - - @Override public String toString() { - return "(" + getRowKey() + "," + getColumnKey() + ")=" + getValue(); - } - } - - /** - * Verifies that {@code rowKey}, {@code columnKey} and {@code value} are - * non-null, and returns a new entry with those values. - */ - static Cell cellOf(R rowKey, C columnKey, V value) { - return immutableCell(checkNotNull(rowKey), checkNotNull(columnKey), - checkNotNull(value)); - } - - /** - * A builder for creating immutable table instances, especially {@code public - * static final} tables ("constant tables"). Example:

   {@code
-   *
-   *   static final ImmutableTable SPREADSHEET =
-   *       new ImmutableTable.Builder()
-   *           .put(1, 'A', "foo")
-   *           .put(1, 'B', "bar")
-   *           .put(2, 'A', "baz")
-   *           .build();}
- * - *

By default, the order in which cells are added to the builder determines - * the iteration ordering of all views in the returned table, with {@link - * #putAll} following the {@link Table#cellSet()} iteration order. However, if - * {@link #orderRowsBy} or {@link #orderColumnsBy} is called, the views are - * sorted by the supplied comparators. - * - * For empty or single-cell immutable tables, {@link #of()} and - * {@link #of(Object, Object, Object)} are even more convenient. - * - *

Builder instances can be reused - it is safe to call {@link #build} - * multiple times to build multiple tables in series. Each table is a superset - * of the tables created before it. - * - * @since 11.0 - */ - public static final class Builder { - private final List> cells = Lists.newArrayList(); - private Comparator rowComparator; - private Comparator columnComparator; - - /** - * Creates a new builder. The returned builder is equivalent to the builder - * generated by {@link ImmutableTable#builder}. - */ - public Builder() {} - - /** - * Specifies the ordering of the generated table's rows. - */ - public Builder orderRowsBy(Comparator rowComparator) { - this.rowComparator = checkNotNull(rowComparator); - return this; - } - - /** - * Specifies the ordering of the generated table's columns. - */ - public Builder orderColumnsBy( - Comparator columnComparator) { - this.columnComparator = checkNotNull(columnComparator); - return this; - } - - /** - * Associates the ({@code rowKey}, {@code columnKey}) pair with {@code - * value} in the built table. Duplicate key pairs are not allowed and will - * cause {@link #build} to fail. - */ - public Builder put(R rowKey, C columnKey, V value) { - cells.add(cellOf(rowKey, columnKey, value)); - return this; - } - - /** - * Adds the given {@code cell} to the table, making it immutable if - * necessary. Duplicate key pairs are not allowed and will cause {@link - * #build} to fail. - */ - public Builder put( - Cell cell) { - if (cell instanceof ImmutableCell) { - checkNotNull(cell.getRowKey()); - checkNotNull(cell.getColumnKey()); - checkNotNull(cell.getValue()); - // all supported methods are covariant - Cell immutableCell = (Cell) cell; - cells.add(immutableCell); - } else { - put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); - } - return this; - } - - /** - * Associates all of the given table's keys and values in the built table. - * Duplicate row key column key pairs are not allowed, and will cause - * {@link #build} to fail. - * - * @throws NullPointerException if any key or value in {@code table} is null - */ - public Builder putAll( - Table table) { - for (Cell cell : table.cellSet()) { - put(cell); - } - return this; - } - - /** - * Returns a newly-created immutable table. - * - * @throws IllegalArgumentException if duplicate key pairs were added - */ - public ImmutableTable build() { - int size = cells.size(); - switch (size) { - case 0: - return of(); -// case 1: -// return new SingletonImmutableTable( -// Iterables.getOnlyElement(cells)); - default: - return RegularImmutableTable.forCells( - cells, rowComparator, columnComparator); - } - } - } - - ImmutableTable() {} - - @Override public ImmutableSet> cellSet() { - return (ImmutableSet>) super.cellSet(); - } - - @Override - abstract ImmutableSet> createCellSet(); - - @Override - final UnmodifiableIterator> cellIterator() { - throw new AssertionError("should never be called"); - } - - @Override - public ImmutableCollection values() { - return (ImmutableCollection) super.values(); - } - - @Override - abstract ImmutableCollection createValues(); - - @Override - final Iterator valuesIterator() { - throw new AssertionError("should never be called"); - } - - private static T firstNonNull(T first, T second) { - return first != null ? first : checkNotNull(second); - } - - /** - * {@inheritDoc} - * - * @throws NullPointerException if {@code columnKey} is {@code null} - */ - @Override public ImmutableMap column(C columnKey) { - checkNotNull(columnKey); - return firstNonNull( - (ImmutableMap) columnMap().get(columnKey), - ImmutableMap.of()); - } - - @Override public ImmutableSet columnKeySet() { - return columnMap().keySet(); - } - - /** - * {@inheritDoc} - * - *

The value {@code Map} instances in the returned map are - * {@link ImmutableMap} instances as well. - */ - @Override public abstract ImmutableMap> columnMap(); - - /** - * {@inheritDoc} - * - * @throws NullPointerException if {@code rowKey} is {@code null} - */ - @Override public ImmutableMap row(R rowKey) { - checkNotNull(rowKey); - return firstNonNull( - (ImmutableMap) rowMap().get(rowKey), - ImmutableMap.of()); - } - - @Override public ImmutableSet rowKeySet() { - return rowMap().keySet(); - } - - /** - * {@inheritDoc} - * - *

The value {@code Map} instances in the returned map are - * {@link ImmutableMap} instances as well. - */ - @Override public abstract ImmutableMap> rowMap(); - - @Override - public boolean contains(Object rowKey, Object columnKey) { - return get(rowKey, columnKey) != null; - } - - @Override - public boolean containsValue(Object value) { - return values().contains(value); - } - - /** - * Guaranteed to throw an exception and leave the table unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated @Override public final void clear() { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the table unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated @Override public final V put(R rowKey, C columnKey, V value) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the table unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated @Override public final void putAll( - Table table) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the table unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated @Override public final V remove(Object rowKey, Object columnKey) { - throw new UnsupportedOperationException(); - } -} diff --git a/java/src/game/collect/Iterables.java b/java/src/game/collect/Iterables.java deleted file mode 100644 index f59524a..0000000 --- a/java/src/game/collect/Iterables.java +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkNotNull; - -import java.util.Iterator; -import java.util.List; -import java.util.RandomAccess; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * This class contains static utility methods that operate on or return objects - * of type {@code Iterable}. Except as noted, each method has a corresponding - * {@link Iterator}-based method in the {@link Iterators} class. - * - *

Performance notes: Unless otherwise noted, all of the iterables - * produced in this class are lazy, which means that their iterators - * only advance the backing iteration when absolutely necessary. - * - *

See the Guava User Guide article on - * {@code Iterables}. - * - * @author Kevin Bourrillion - * @author Jared Levy - * @since 2.0 (imported from Google Collections Library) - */ - -public final class Iterables { - private Iterables() {} - - /** Returns an unmodifiable view of {@code iterable}. */ -// public static Iterable unmodifiableIterable( -// final Iterable iterable) { -// checkNotNull(iterable); -// if (iterable instanceof UnmodifiableIterable || -// iterable instanceof ImmutableCollection) { -// return iterable; -// } -// return new UnmodifiableIterable(iterable); -// } - - /** - * Simply returns its argument. - * - * @deprecated no need to use this - * @since 10.0 - */ -// @Deprecated public static Iterable unmodifiableIterable( -// ImmutableCollection iterable) { -// return checkNotNull(iterable); -// } - -// private static final class UnmodifiableIterable extends FluentIterable { -// private final Iterable iterable; -// -// private UnmodifiableIterable(Iterable iterable) { -// this.iterable = iterable; -// } -// -// @Override -// public Iterator iterator() { -// return Iterators.unmodifiableIterator(iterable.iterator()); -// } -// -// @Override -// public String toString() { -// return iterable.toString(); -// } -// // no equals and hashCode; it would break the contract! -// } - - /** - * Returns the number of elements in {@code iterable}. - */ -// public static int size(Iterable iterable) { -// return (iterable instanceof Collection) -// ? ((Collection) iterable).size() -// : Iterators.size(iterable.iterator()); -// } - - /** - * Returns {@code true} if {@code iterable} contains any object for which {@code equals(element)} - * is true. - */ -// public static boolean contains(Iterable iterable, Object element) { -// if (iterable instanceof Collection) { -// Collection collection = (Collection) iterable; -// return Collections2.safeContains(collection, element); -// } -// return Iterators.contains(iterable.iterator(), element); -// } - - /** - * Removes, from an iterable, every element that belongs to the provided - * collection. - * - *

This method calls {@link Collection#removeAll} if {@code iterable} is a - * collection, and {@link Iterators#removeAll} otherwise. - * - * @param removeFrom the iterable to (potentially) remove elements from - * @param elementsToRemove the elements to remove - * @return {@code true} if any element was removed from {@code iterable} - */ -// public static boolean removeAll( -// Iterable removeFrom, Collection elementsToRemove) { -// return (removeFrom instanceof Collection) -// ? ((Collection) removeFrom).removeAll(checkNotNull(elementsToRemove)) -// : Iterators.removeAll(removeFrom.iterator(), elementsToRemove); -// } - - /** - * Removes, from an iterable, every element that does not belong to the - * provided collection. - * - *

This method calls {@link Collection#retainAll} if {@code iterable} is a - * collection, and {@link Iterators#retainAll} otherwise. - * - * @param removeFrom the iterable to (potentially) remove elements from - * @param elementsToRetain the elements to retain - * @return {@code true} if any element was removed from {@code iterable} - */ -// public static boolean retainAll( -// Iterable removeFrom, Collection elementsToRetain) { -// return (removeFrom instanceof Collection) -// ? ((Collection) removeFrom).retainAll(checkNotNull(elementsToRetain)) -// : Iterators.retainAll(removeFrom.iterator(), elementsToRetain); -// } - - /** - * Removes, from an iterable, every element that satisfies the provided - * predicate. - * - * @param removeFrom the iterable to (potentially) remove elements from - * @param predicate a predicate that determines whether an element should - * be removed - * @return {@code true} if any elements were removed from the iterable - * - * @throws UnsupportedOperationException if the iterable does not support - * {@code remove()}. - * @since 2.0 - */ - public static boolean removeIf( - Iterable removeFrom, Predicate predicate) { - if (removeFrom instanceof RandomAccess && removeFrom instanceof List) { - return removeIfFromRandomAccessList( - (List) removeFrom, checkNotNull(predicate)); - } - return Iterators.removeIf(removeFrom.iterator(), predicate); - } - - private static boolean removeIfFromRandomAccessList( - List list, Predicate predicate) { - // Note: Not all random access lists support set() so we need to deal with - // those that don't and attempt the slower remove() based solution. - int from = 0; - int to = 0; - - for (; from < list.size(); from++) { - T element = list.get(from); - if (!predicate.test(element)) { - if (from > to) { - try { - list.set(to, element); - } catch (UnsupportedOperationException e) { - slowRemoveIfForRemainingElements(list, predicate, to, from); - return true; - } - } - to++; - } - } - - // Clear the tail of any remaining items - list.subList(to, list.size()).clear(); - return from != to; - } - - private static void slowRemoveIfForRemainingElements(List list, - Predicate predicate, int to, int from) { - // Here we know that: - // * (to < from) and that both are valid indices. - // * Everything with (index < to) should be kept. - // * Everything with (to <= index < from) should be removed. - // * The element with (index == from) should be kept. - // * Everything with (index > from) has not been checked yet. - - // Check from the end of the list backwards (minimize expected cost of - // moving elements when remove() is called). Stop before 'from' because - // we already know that should be kept. - for (int n = list.size() - 1; n > from; n--) { - if (predicate.test(list.get(n))) { - list.remove(n); - } - } - // And now remove everything in the range [to, from) (going backwards). - for (int n = from - 1; n >= to; n--) { - list.remove(n); - } - } - - /** - * Removes and returns the first matching element, or returns {@code null} if there is none. - */ -// -// static T removeFirstMatching(Iterable removeFrom, Predicate predicate) { -// checkNotNull(predicate); -// Iterator iterator = removeFrom.iterator(); -// while (iterator.hasNext()) { -// T next = iterator.next(); -// if (predicate.apply(next)) { -// iterator.remove(); -// return next; -// } -// } -// return null; -// } - - /** - * Determines whether two iterables contain equal elements in the same order. - * More specifically, this method returns {@code true} if {@code iterable1} - * and {@code iterable2} contain the same number of elements and every element - * of {@code iterable1} is equal to the corresponding element of - * {@code iterable2}. - */ -// public static boolean elementsEqual( -// Iterable iterable1, Iterable iterable2) { -// if (iterable1 instanceof Collection && iterable2 instanceof Collection) { -// Collection collection1 = (Collection) iterable1; -// Collection collection2 = (Collection) iterable2; -// if (collection1.size() != collection2.size()) { -// return false; -// } -// } -// return Iterators.elementsEqual(iterable1.iterator(), iterable2.iterator()); -// } - - /** - * Returns a string representation of {@code iterable}, with the format {@code - * [e1, e2, ..., en]} (that is, identical to {@link java.util.Arrays - * Arrays}{@code .toString(Iterables.toArray(iterable))}). Note that for - * most implementations of {@link Collection}, {@code - * collection.toString()} also gives the same result, but that behavior is not - * generally guaranteed. - */ -// public static String toString(Iterable iterable) { -// return Iterators.toString(iterable.iterator()); -// } - - /** - * Returns the single element contained in {@code iterable}. - * - * @throws NoSuchElementException if the iterable is empty - * @throws IllegalArgumentException if the iterable contains multiple - * elements - */ -// public static T getOnlyElement(Iterable iterable) { -// return Iterators.getOnlyElement(iterable.iterator()); -// } - - /** - * Returns the single element contained in {@code iterable}, or {@code - * defaultValue} if the iterable is empty. - * - * @throws IllegalArgumentException if the iterator contains multiple - * elements - */ -// -// public static T getOnlyElement( -// Iterable iterable, T defaultValue) { -// return Iterators.getOnlyElement(iterable.iterator(), defaultValue); -// } - - /** - * Copies an iterable's elements into an array. - * - * @param iterable the iterable to copy - * @param type the type of the elements - * @return a newly-allocated array into which all the elements of the iterable - * have been copied - */ -// -// public static T[] toArray(Iterable iterable, Class type) { -// Collection collection = toCollection(iterable); -// T[] array = ObjectArrays.newArray(type, collection.size()); -// return collection.toArray(array); -// } - - /** - * Copies an iterable's elements into an array. - * - * @param iterable the iterable to copy - * @return a newly-allocated array into which all the elements of the iterable - * have been copied - */ -// static Object[] toArray(Iterable iterable) { -// return toCollection(iterable).toArray(); -// } - - /** - * Converts an iterable into a collection. If the iterable is already a - * collection, it is returned. Otherwise, an {@link java.util.ArrayList} is - * created with the contents of the iterable in the same iteration order. - */ -// private static Collection toCollection(Iterable iterable) { -// return (iterable instanceof Collection) -// ? (Collection) iterable -// : Lists.newArrayList(iterable.iterator()); -// } - - /** - * Adds all elements in {@code iterable} to {@code collection}. - * - * @return {@code true} if {@code collection} was modified as a result of this - * operation. - */ -// public static boolean addAll( -// Collection addTo, Iterable elementsToAdd) { -// if (elementsToAdd instanceof Collection) { -// Collection c = Collections2.cast(elementsToAdd); -// return addTo.addAll(c); -// } -// return Iterators.addAll(addTo, checkNotNull(elementsToAdd).iterator()); -// } - - /** - * Returns the number of elements in the specified iterable that equal the - * specified object. This implementation avoids a full iteration when the - * iterable is a {@link Multiset} or {@link Set}. - * - * @see Collections#frequency - */ -// public static int frequency(Iterable iterable, Object element) { -// if ((iterable instanceof Multiset)) { -// return ((Multiset) iterable).count(element); -// } else if ((iterable instanceof Set)) { -// return ((Set) iterable).contains(element) ? 1 : 0; -// } -// return Iterators.frequency(iterable.iterator(), element); -// } - - /** - * Returns an iterable whose iterators cycle indefinitely over the elements of - * {@code iterable}. - * - *

That iterator supports {@code remove()} if {@code iterable.iterator()} - * does. After {@code remove()} is called, subsequent cycles omit the removed - * element, which is no longer in {@code iterable}. The iterator's - * {@code hasNext()} method returns {@code true} until {@code iterable} is - * empty. - * - *

Warning: Typical uses of the resulting iterator may produce an - * infinite loop. You should use an explicit {@code break} or be certain that - * you will eventually remove all the elements. - * - *

To cycle over the iterable {@code n} times, use the following: - * {@code Iterables.concat(Collections.nCopies(n, iterable))} - */ -// public static Iterable cycle(final Iterable iterable) { -// checkNotNull(iterable); -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// return Iterators.cycle(iterable); -// } -// @Override public String toString() { -// return iterable.toString() + " (cycled)"; -// } -// }; -// } - - /** - * Returns an iterable whose iterators cycle indefinitely over the provided - * elements. - * - *

After {@code remove} is invoked on a generated iterator, the removed - * element will no longer appear in either that iterator or any other iterator - * created from the same source iterable. That is, this method behaves exactly - * as {@code Iterables.cycle(Lists.newArrayList(elements))}. The iterator's - * {@code hasNext} method returns {@code true} until all of the original - * elements have been removed. - * - *

Warning: Typical uses of the resulting iterator may produce an - * infinite loop. You should use an explicit {@code break} or be certain that - * you will eventually remove all the elements. - * - *

To cycle over the elements {@code n} times, use the following: - * {@code Iterables.concat(Collections.nCopies(n, Arrays.asList(elements)))} - */ -// public static Iterable cycle(T... elements) { -// return cycle(Lists.newArrayList(elements)); -// } - - /** - * Combines two iterables into a single iterable. The returned iterable has an - * iterator that traverses the elements in {@code a}, followed by the elements - * in {@code b}. The source iterators are not polled until necessary. - * - *

The returned iterable's iterator supports {@code remove()} when the - * corresponding input iterator supports it. - */ -// public static Iterable concat( -// Iterable a, Iterable b) { -// return concat(ImmutableList.of(a, b)); -// } - - /** - * Combines three iterables into a single iterable. The returned iterable has - * an iterator that traverses the elements in {@code a}, followed by the - * elements in {@code b}, followed by the elements in {@code c}. The source - * iterators are not polled until necessary. - * - *

The returned iterable's iterator supports {@code remove()} when the - * corresponding input iterator supports it. - */ -// public static Iterable concat(Iterable a, -// Iterable b, Iterable c) { -// return concat(ImmutableList.of(a, b, c)); -// } - - /** - * Combines four iterables into a single iterable. The returned iterable has - * an iterator that traverses the elements in {@code a}, followed by the - * elements in {@code b}, followed by the elements in {@code c}, followed by - * the elements in {@code d}. The source iterators are not polled until - * necessary. - * - *

The returned iterable's iterator supports {@code remove()} when the - * corresponding input iterator supports it. - */ -// public static Iterable concat(Iterable a, -// Iterable b, Iterable c, -// Iterable d) { -// return concat(ImmutableList.of(a, b, c, d)); -// } - - /** - * Combines multiple iterables into a single iterable. The returned iterable - * has an iterator that traverses the elements of each iterable in - * {@code inputs}. The input iterators are not polled until necessary. - * - *

The returned iterable's iterator supports {@code remove()} when the - * corresponding input iterator supports it. - * - * @throws NullPointerException if any of the provided iterables is null - */ -// public static Iterable concat(Iterable... inputs) { -// return concat(ImmutableList.copyOf(inputs)); -// } - - /** - * Combines multiple iterables into a single iterable. The returned iterable - * has an iterator that traverses the elements of each iterable in - * {@code inputs}. The input iterators are not polled until necessary. - * - *

The returned iterable's iterator supports {@code remove()} when the - * corresponding input iterator supports it. The methods of the returned - * iterable may throw {@code NullPointerException} if any of the input - * iterators is null. - */ -// public static Iterable concat( -// final Iterable> inputs) { -// checkNotNull(inputs); -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// return Iterators.concat(iterators(inputs)); -// } -// }; -// } - - /** - * Returns an iterator over the iterators of the given iterables. - */ -// private static Iterator> iterators( -// Iterable> iterables) { -// return new TransformedIterator, Iterator>( -// iterables.iterator()) { -// @Override -// Iterator transform(Iterable from) { -// return from.iterator(); -// } -// }; -// } - - /** - * Divides an iterable into unmodifiable sublists of the given size (the final - * iterable may be smaller). For example, partitioning an iterable containing - * {@code [a, b, c, d, e]} with a partition size of 3 yields {@code - * [[a, b, c], [d, e]]} -- an outer iterable containing two inner lists of - * three and two elements, all in the original order. - * - *

Iterators returned by the returned iterable do not support the {@link - * Iterator#remove()} method. The returned lists implement {@link - * RandomAccess}, whether or not the input list does. - * - *

Note: if {@code iterable} is a {@link List}, use {@link - * Lists#partition(List, int)} instead. - * - * @param iterable the iterable to return a partitioned view of - * @param size the desired size of each partition (the last may be smaller) - * @return an iterable of unmodifiable lists containing the elements of {@code - * iterable} divided into partitions - * @throws IllegalArgumentException if {@code size} is nonpositive - */ -// public static Iterable> partition( -// final Iterable iterable, final int size) { -// checkNotNull(iterable); -// checkArgument(size > 0); -// return new FluentIterable>() { -// @Override -// public Iterator> iterator() { -// return Iterators.partition(iterable.iterator(), size); -// } -// }; -// } - - /** - * Divides an iterable into unmodifiable sublists of the given size, padding - * the final iterable with null values if necessary. For example, partitioning - * an iterable containing {@code [a, b, c, d, e]} with a partition size of 3 - * yields {@code [[a, b, c], [d, e, null]]} -- an outer iterable containing - * two inner lists of three elements each, all in the original order. - * - *

Iterators returned by the returned iterable do not support the {@link - * Iterator#remove()} method. - * - * @param iterable the iterable to return a partitioned view of - * @param size the desired size of each partition - * @return an iterable of unmodifiable lists containing the elements of {@code - * iterable} divided into partitions (the final iterable may have - * trailing null elements) - * @throws IllegalArgumentException if {@code size} is nonpositive - */ -// public static Iterable> paddedPartition( -// final Iterable iterable, final int size) { -// checkNotNull(iterable); -// checkArgument(size > 0); -// return new FluentIterable>() { -// @Override -// public Iterator> iterator() { -// return Iterators.paddedPartition(iterable.iterator(), size); -// } -// }; -// } - - /** - * Returns the elements of {@code unfiltered} that satisfy a predicate. The - * resulting iterable's iterator does not support {@code remove()}. - */ -// public static Iterable filter( -// final Iterable unfiltered, final Predicate predicate) { -// checkNotNull(unfiltered); -// checkNotNull(predicate); -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// return Iterators.filter(unfiltered.iterator(), predicate); -// } -// }; -// } - - /** - * Returns all instances of class {@code type} in {@code unfiltered}. The - * returned iterable has elements whose class is {@code type} or a subclass of - * {@code type}. The returned iterable's iterator does not support - * {@code remove()}. - * - * @param unfiltered an iterable containing objects of any type - * @param type the type of elements desired - * @return an unmodifiable iterable containing all elements of the original - * iterable that were of the requested type - */ -// -// public static Iterable filter( -// final Iterable unfiltered, final Class type) { -// checkNotNull(unfiltered); -// checkNotNull(type); -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// return Iterators.filter(unfiltered.iterator(), type); -// } -// }; -// } - - /** - * Returns {@code true} if any element in {@code iterable} satisfies the predicate. - */ - public static boolean any( - Iterable iterable, Predicate predicate) { - return Iterators.any(iterable.iterator(), predicate); - } - - /** - * Returns {@code true} if every element in {@code iterable} satisfies the - * predicate. If {@code iterable} is empty, {@code true} is returned. - */ - public static boolean all( - Iterable iterable, Predicate predicate) { - return Iterators.all(iterable.iterator(), predicate); - } - - /** - * Returns the first element in {@code iterable} that satisfies the given - * predicate; use this method only when such an element is known to exist. If - * it is possible that no element will match, use {@link #tryFind} or - * {@link #find(Iterable, Predicate, Object)} instead. - * - * @throws NoSuchElementException if no element in {@code iterable} matches - * the given predicate - */ -// public static T find(Iterable iterable, -// Predicate predicate) { -// return Iterators.find(iterable.iterator(), predicate); -// } - - /** - * Returns the first element in {@code iterable} that satisfies the given - * predicate, or {@code defaultValue} if none found. Note that this can - * usually be handled more naturally using {@code - * tryFind(iterable, predicate).or(defaultValue)}. - * - * @since 7.0 - */ -// -// public static T find(Iterable iterable, -// Predicate predicate, T defaultValue) { -// return Iterators.find(iterable.iterator(), predicate, defaultValue); -// } - - /** - * Returns an {@link Optional} containing the first element in {@code - * iterable} that satisfies the given predicate, if such an element exists. - * - *

Warning: avoid using a {@code predicate} that matches {@code - * null}. If {@code null} is matched in {@code iterable}, a - * NullPointerException will be thrown. - * - * @since 11.0 - */ -// public static Optional tryFind(Iterable iterable, -// Predicate predicate) { -// return Iterators.tryFind(iterable.iterator(), predicate); -// } - - /** - * Returns the index in {@code iterable} of the first element that satisfies - * the provided {@code predicate}, or {@code -1} if the Iterable has no such - * elements. - * - *

More formally, returns the lowest index {@code i} such that - * {@code predicate.apply(Iterables.get(iterable, i))} returns {@code true}, - * or {@code -1} if there is no such index. - * - * @since 2.0 - */ -// public static int indexOf( -// Iterable iterable, Predicate predicate) { -// return Iterators.indexOf(iterable.iterator(), predicate); -// } - - /** - * Returns an iterable that applies {@code function} to each element of {@code - * fromIterable}. - * - *

The returned iterable's iterator supports {@code remove()} if the - * provided iterator does. After a successful {@code remove()} call, - * {@code fromIterable} no longer contains the corresponding element. - * - *

If the input {@code Iterable} is known to be a {@code List} or other - * {@code Collection}, consider {@link Lists#transform} and {@link - * Collections2#transform}. - */ - public static Iterable transform(final Iterable fromIterable, - final Function function) { - checkNotNull(fromIterable); - checkNotNull(function); - return new Iterable() { - @Override - public Iterator iterator() { - return Iterators.transform(fromIterable.iterator(), function); - } - }; - } - - /** - * Returns the element at the specified position in an iterable. - * - * @param position position of the element to return - * @return the element at the specified position in {@code iterable} - * @throws IndexOutOfBoundsException if {@code position} is negative or - * greater than or equal to the size of {@code iterable} - */ -// public static T get(Iterable iterable, int position) { -// checkNotNull(iterable); -// return (iterable instanceof List) -// ? ((List) iterable).get(position) -// : Iterators.get(iterable.iterator(), position); -// } - - /** - * Returns the element at the specified position in an iterable or a default - * value otherwise. - * - * @param position position of the element to return - * @param defaultValue the default value to return if {@code position} is - * greater than or equal to the size of the iterable - * @return the element at the specified position in {@code iterable} or - * {@code defaultValue} if {@code iterable} contains fewer than - * {@code position + 1} elements. - * @throws IndexOutOfBoundsException if {@code position} is negative - * @since 4.0 - */ -// -// public static T get(Iterable iterable, int position, T defaultValue) { -// checkNotNull(iterable); -// Iterators.checkNonnegative(position); -// if (iterable instanceof List) { -// List list = Lists.cast(iterable); -// return (position < list.size()) ? list.get(position) : defaultValue; -// } else { -// Iterator iterator = iterable.iterator(); -// Iterators.advance(iterator, position); -// return Iterators.getNext(iterator, defaultValue); -// } -// } - - /** - * Returns the first element in {@code iterable} or {@code defaultValue} if - * the iterable is empty. The {@link Iterators} analog to this method is - * {@link Iterators#getNext}. - * - *

If no default value is desired (and the caller instead wants a - * {@link NoSuchElementException} to be thrown), it is recommended that - * {@code iterable.iterator().next()} is used instead. - * - * @param defaultValue the default value to return if the iterable is empty - * @return the first element of {@code iterable} or the default value - * @since 7.0 - */ -// -// public static T getFirst(Iterable iterable, T defaultValue) { -// return Iterators.getNext(iterable.iterator(), defaultValue); -// } - - /** - * Returns the last element of {@code iterable}. - * - * @return the last element of {@code iterable} - * @throws NoSuchElementException if the iterable is empty - */ -// public static T getLast(Iterable iterable) { -// // TODO(kevinb): Support a concurrently modified collection? -// if (iterable instanceof List) { -// List list = (List) iterable; -// if (list.isEmpty()) { -// throw new NoSuchElementException(); -// } -// return getLastInNonemptyList(list); -// } -// -// return Iterators.getLast(iterable.iterator()); -// } - - /** - * Returns the last element of {@code iterable} or {@code defaultValue} if - * the iterable is empty. - * - * @param defaultValue the value to return if {@code iterable} is empty - * @return the last element of {@code iterable} or the default value - * @since 3.0 - */ -// -// public static T getLast(Iterable iterable, T defaultValue) { -// if (iterable instanceof Collection) { -// Collection c = Collections2.cast(iterable); -// if (c.isEmpty()) { -// return defaultValue; -// } else if (iterable instanceof List) { -// return getLastInNonemptyList(Lists.cast(iterable)); -// } -// } -// -// return Iterators.getLast(iterable.iterator(), defaultValue); -// } -// -// private static T getLastInNonemptyList(List list) { -// return list.get(list.size() - 1); -// } - - /** - * Returns a view of {@code iterable} that skips its first - * {@code numberToSkip} elements. If {@code iterable} contains fewer than - * {@code numberToSkip} elements, the returned iterable skips all of its - * elements. - * - *

Modifications to the underlying {@link Iterable} before a call to - * {@code iterator()} are reflected in the returned iterator. That is, the - * iterator skips the first {@code numberToSkip} elements that exist when the - * {@code Iterator} is created, not when {@code skip()} is called. - * - *

The returned iterable's iterator supports {@code remove()} if the - * iterator of the underlying iterable supports it. Note that it is - * not possible to delete the last skipped element by immediately - * calling {@code remove()} on that iterator, as the {@code Iterator} - * contract states that a call to {@code remove()} before a call to - * {@code next()} will throw an {@link IllegalStateException}. - * - * @since 3.0 - */ -// public static Iterable skip(final Iterable iterable, -// final int numberToSkip) { -// checkNotNull(iterable); -// checkArgument(numberToSkip >= 0, "number to skip cannot be negative"); -// -// if (iterable instanceof List) { -// final List list = (List) iterable; -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// // TODO(kevinb): Support a concurrently modified collection? -// int toSkip = Math.min(list.size(), numberToSkip); -// return list.subList(toSkip, list.size()).iterator(); -// } -// }; -// } -// -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// final Iterator iterator = iterable.iterator(); -// -// Iterators.advance(iterator, numberToSkip); -// -// /* -// * We can't just return the iterator because an immediate call to its -// * remove() method would remove one of the skipped elements instead of -// * throwing an IllegalStateException. -// */ -// return new Iterator() { -// boolean atStart = true; -// -// @Override -// public boolean hasNext() { -// return iterator.hasNext(); -// } -// -// @Override -// public T next() { -// T result = iterator.next(); -// atStart = false; // not called if next() fails -// return result; -// } -// -// @Override -// public void remove() { -// checkRemove(!atStart); -// iterator.remove(); -// } -// }; -// } -// }; -// } - - /** - * Creates an iterable with the first {@code limitSize} elements of the given - * iterable. If the original iterable does not contain that many elements, the - * returned iterable will have the same behavior as the original iterable. The - * returned iterable's iterator supports {@code remove()} if the original - * iterator does. - * - * @param iterable the iterable to limit - * @param limitSize the maximum number of elements in the returned iterable - * @throws IllegalArgumentException if {@code limitSize} is negative - * @since 3.0 - */ -// public static Iterable limit( -// final Iterable iterable, final int limitSize) { -// checkNotNull(iterable); -// checkArgument(limitSize >= 0, "limit is negative"); -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// return Iterators.limit(iterable.iterator(), limitSize); -// } -// }; -// } - - /** - * Returns a view of the supplied iterable that wraps each generated - * {@link Iterator} through {@link Iterators#consumingIterator(Iterator)}. - * - *

Note: If {@code iterable} is a {@link Queue}, the returned iterable will - * get entries from {@link Queue#remove()} since {@link Queue}'s iteration - * order is undefined. Calling {@link Iterator#hasNext()} on a generated - * iterator from the returned iterable may cause an item to be immediately - * dequeued for return on a subsequent call to {@link Iterator#next()}. - * - * @param iterable the iterable to wrap - * @return a view of the supplied iterable that wraps each generated iterator - * through {@link Iterators#consumingIterator(Iterator)}; for queues, - * an iterable that generates iterators that return and consume the - * queue's elements in queue order - * - * @see Iterators#consumingIterator(Iterator) - * @since 2.0 - */ -// public static Iterable consumingIterable(final Iterable iterable) { -// if (iterable instanceof Queue) { -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// return new ConsumingQueueIterator((Queue) iterable); -// } -// -// @Override -// public String toString() { -// return "Iterables.consumingIterable(...)"; -// } -// }; -// } -// -// checkNotNull(iterable); -// -// return new FluentIterable() { -// @Override -// public Iterator iterator() { -// return Iterators.consumingIterator(iterable.iterator()); -// } -// -// @Override -// public String toString() { -// return "Iterables.consumingIterable(...)"; -// } -// }; -// } -// -// private static class ConsumingQueueIterator extends AbstractIterator { -// private final Queue queue; -// -// private ConsumingQueueIterator(Queue queue) { -// this.queue = queue; -// } -// -// @Override public T computeNext() { -// try { -// return queue.remove(); -// } catch (NoSuchElementException e) { -// return endOfData(); -// } -// } -// } - - // Methods only in Iterables, not in Iterators - - /** - * Determines if the given iterable contains no elements. - * - *

There is no precise {@link Iterator} equivalent to this method, since - * one can only ask an iterator whether it has any elements remaining - * (which one does using {@link Iterator#hasNext}). - * - * @return {@code true} if the iterable contains no elements - */ -// public static boolean isEmpty(Iterable iterable) { -// if (iterable instanceof Collection) { -// return ((Collection) iterable).isEmpty(); -// } -// return !iterable.iterator().hasNext(); -// } - - /** - * Returns an iterable over the merged contents of all given - * {@code iterables}. Equivalent entries will not be de-duplicated. - * - *

Callers must ensure that the source {@code iterables} are in - * non-descending order as this method does not sort its input. - * - *

For any equivalent elements across all {@code iterables}, it is - * undefined which element is returned first. - * - * @since 11.0 - */ -// @Beta -// public static Iterable mergeSorted( -// final Iterable> iterables, -// final Comparator comparator) { -// checkNotNull(iterables, "iterables"); -// checkNotNull(comparator, "comparator"); -// Iterable iterable = new FluentIterable() { -// @Override -// public Iterator iterator() { -// return Iterators.mergeSorted( -// Iterables.transform(iterables, Iterables.toIterator()), -// comparator); -// } -// }; -// return new UnmodifiableIterable(iterable); -// } - - // TODO(user): Is this the best place for this? Move to fluent functions? - // Useful as a public method? -// private static Function, Iterator> -// toIterator() { -// return new Function, Iterator>() { -// @Override -// public Iterator apply(Iterable iterable) { -// return iterable.iterator(); -// } -// }; -// } -} diff --git a/java/src/game/collect/Iterators.java b/java/src/game/collect/Iterators.java deleted file mode 100644 index 49325ab..0000000 --- a/java/src/game/collect/Iterators.java +++ /dev/null @@ -1,1296 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkRemove; -import static game.collect.Preconditions.checkArgument; -import static game.collect.Preconditions.checkNotNull; -import static game.util.Predicates.equalTo; -import static game.util.Predicates.in; -import static game.util.Predicates.instanceOf; -import static game.util.Predicates.not; - -import java.util.Collection; -import java.util.Iterator; -import java.util.ListIterator; -import java.util.NoSuchElementException; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * This class contains static utility methods that operate on or return objects - * of type {@link Iterator}. Except as noted, each method has a corresponding - * {@link Iterable}-based method in the {@link Iterables} class. - * - *

Performance notes: Unless otherwise noted, all of the iterators - * produced in this class are lazy, which means that they only advance - * the backing iteration when absolutely necessary. - * - *

See the Guava User Guide section on - * {@code Iterators}. - * - * @author Kevin Bourrillion - * @author Jared Levy - * @since 2.0 (imported from Google Collections Library) - */ - -public final class Iterators { - private Iterators() {} - - static final UnmodifiableListIterator EMPTY_LIST_ITERATOR - = new UnmodifiableListIterator() { - @Override - public boolean hasNext() { - return false; - } - @Override - public Object next() { - throw new NoSuchElementException(); - } - @Override - public boolean hasPrevious() { - return false; - } - @Override - public Object previous() { - throw new NoSuchElementException(); - } - @Override - public int nextIndex() { - return 0; - } - @Override - public int previousIndex() { - return -1; - } - }; - - /** - * Returns the empty iterator. - * - *

The {@link Iterable} equivalent of this method is {@link - * ImmutableSet#of()}. - */ - public static UnmodifiableIterator emptyIterator() { - return emptyListIterator(); - } - - /** - * Returns the empty iterator. - * - *

The {@link Iterable} equivalent of this method is {@link - * ImmutableSet#of()}. - */ - // Casting to any type is safe since there are no actual elements. - - static UnmodifiableListIterator emptyListIterator() { - return (UnmodifiableListIterator) EMPTY_LIST_ITERATOR; - } - - private static final Iterator EMPTY_MODIFIABLE_ITERATOR = - new Iterator() { - @Override public boolean hasNext() { - return false; - } - - @Override public Object next() { - throw new NoSuchElementException(); - } - - @Override public void remove() { - checkRemove(false); - } - }; - - /** - * Returns the empty {@code Iterator} that throws - * {@link IllegalStateException} instead of - * {@link UnsupportedOperationException} on a call to - * {@link Iterator#remove()}. - */ - // Casting to any type is safe since there are no actual elements. - - static Iterator emptyModifiableIterator() { - return (Iterator) EMPTY_MODIFIABLE_ITERATOR; - } - - /** Returns an unmodifiable view of {@code iterator}. */ - public static UnmodifiableIterator unmodifiableIterator( - final Iterator iterator) { - checkNotNull(iterator); - if (iterator instanceof UnmodifiableIterator) { - return (UnmodifiableIterator) iterator; - } - return new UnmodifiableIterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - @Override - public T next() { - return iterator.next(); - } - }; - } - - /** - * Simply returns its argument. - * - * @deprecated no need to use this - * @since 10.0 - */ -// @Deprecated public static UnmodifiableIterator unmodifiableIterator( -// UnmodifiableIterator iterator) { -// return checkNotNull(iterator); -// } - - /** - * Returns the number of elements remaining in {@code iterator}. The iterator - * will be left exhausted: its {@code hasNext()} method will return - * {@code false}. - */ - public static int size(Iterator iterator) { - int count = 0; - while (iterator.hasNext()) { - iterator.next(); - count++; - } - return count; - } - - /** - * Returns {@code true} if {@code iterator} contains {@code element}. - */ - public static boolean contains(Iterator iterator, Object element) { - return any(iterator, equalTo(element)); - } - - /** - * Traverses an iterator and removes every element that belongs to the - * provided collection. The iterator will be left exhausted: its - * {@code hasNext()} method will return {@code false}. - * - * @param removeFrom the iterator to (potentially) remove elements from - * @param elementsToRemove the elements to remove - * @return {@code true} if any element was removed from {@code iterator} - */ - public static boolean removeAll( - Iterator removeFrom, Collection elementsToRemove) { - return removeIf(removeFrom, in(elementsToRemove)); - } - - /** - * Removes every element that satisfies the provided predicate from the - * iterator. The iterator will be left exhausted: its {@code hasNext()} - * method will return {@code false}. - * - * @param removeFrom the iterator to (potentially) remove elements from - * @param predicate a predicate that determines whether an element should - * be removed - * @return {@code true} if any elements were removed from the iterator - * @since 2.0 - */ - public static boolean removeIf( - Iterator removeFrom, Predicate predicate) { - checkNotNull(predicate); - boolean modified = false; - while (removeFrom.hasNext()) { - if (predicate.test(removeFrom.next())) { - removeFrom.remove(); - modified = true; - } - } - return modified; - } - - /** - * Traverses an iterator and removes every element that does not belong to the - * provided collection. The iterator will be left exhausted: its - * {@code hasNext()} method will return {@code false}. - * - * @param removeFrom the iterator to (potentially) remove elements from - * @param elementsToRetain the elements to retain - * @return {@code true} if any element was removed from {@code iterator} - */ - public static boolean retainAll( - Iterator removeFrom, Collection elementsToRetain) { - return removeIf(removeFrom, not(in(elementsToRetain))); - } - - /** - * Determines whether two iterators contain equal elements in the same order. - * More specifically, this method returns {@code true} if {@code iterator1} - * and {@code iterator2} contain the same number of elements and every element - * of {@code iterator1} is equal to the corresponding element of - * {@code iterator2}. - * - *

Note that this will modify the supplied iterators, since they will have - * been advanced some number of elements forward. - */ - public static boolean elementsEqual( - Iterator iterator1, Iterator iterator2) { - while (iterator1.hasNext()) { - if (!iterator2.hasNext()) { - return false; - } - Object o1 = iterator1.next(); - Object o2 = iterator2.next(); - if (!Preconditions.equal(o1, o2)) { - return false; - } - } - return !iterator2.hasNext(); - } - - /** - * Returns a string representation of {@code iterator}, with the format - * {@code [e1, e2, ..., en]}. The iterator will be left exhausted: its - * {@code hasNext()} method will return {@code false}. - */ -// public static String toString(Iterator iterator) { -// return Collections2.STANDARD_JOINER -// .appendTo(new StringBuilder().append('['), iterator) -// .append(']') -// .toString(); -// } - - /** - * Returns the single element contained in {@code iterator}. - * - * @throws NoSuchElementException if the iterator is empty - * @throws IllegalArgumentException if the iterator contains multiple - * elements. The state of the iterator is unspecified. - */ -// public static T getOnlyElement(Iterator iterator) { -// T first = iterator.next(); -// if (!iterator.hasNext()) { -// return first; -// } -// -// StringBuilder sb = new StringBuilder(); -// sb.append("expected one element but was: <" + first); -// for (int i = 0; i < 4 && iterator.hasNext(); i++) { -// sb.append(", " + iterator.next()); -// } -// if (iterator.hasNext()) { -// sb.append(", ..."); -// } -// sb.append('>'); -// -// throw new IllegalArgumentException(sb.toString()); -// } - - /** - * Returns the single element contained in {@code iterator}, or {@code - * defaultValue} if the iterator is empty. - * - * @throws IllegalArgumentException if the iterator contains multiple - * elements. The state of the iterator is unspecified. - */ -// -// public static T getOnlyElement(Iterator iterator, T defaultValue) { -// return iterator.hasNext() ? getOnlyElement(iterator) : defaultValue; -// } - - /** - * Copies an iterator's elements into an array. The iterator will be left - * exhausted: its {@code hasNext()} method will return {@code false}. - * - * @param iterator the iterator to copy - * @param type the type of the elements - * @return a newly-allocated array into which all the elements of the iterator - * have been copied - */ -// -// public static T[] toArray( -// Iterator iterator, Class type) { -// List list = Lists.newArrayList(iterator); -// return Iterables.toArray(list, type); -// } - - /** - * Adds all elements in {@code iterator} to {@code collection}. The iterator - * will be left exhausted: its {@code hasNext()} method will return - * {@code false}. - * - * @return {@code true} if {@code collection} was modified as a result of this - * operation - */ - public static boolean addAll( - Collection addTo, Iterator iterator) { - checkNotNull(addTo); - checkNotNull(iterator); - boolean wasModified = false; - while (iterator.hasNext()) { - wasModified |= addTo.add(iterator.next()); - } - return wasModified; - } - - /** - * Returns the number of elements in the specified iterator that equal the - * specified object. The iterator will be left exhausted: its - * {@code hasNext()} method will return {@code false}. - * - * @see Collections#frequency - */ -// public static int frequency(Iterator iterator, Object element) { -// return size(filter(iterator, equalTo(element))); -// } - - /** - * Returns an iterator that cycles indefinitely over the elements of {@code - * iterable}. - * - *

The returned iterator supports {@code remove()} if the provided iterator - * does. After {@code remove()} is called, subsequent cycles omit the removed - * element, which is no longer in {@code iterable}. The iterator's - * {@code hasNext()} method returns {@code true} until {@code iterable} is - * empty. - * - *

Warning: Typical uses of the resulting iterator may produce an - * infinite loop. You should use an explicit {@code break} or be certain that - * you will eventually remove all the elements. - */ -// public static Iterator cycle(final Iterable iterable) { -// checkNotNull(iterable); -// return new Iterator() { -// Iterator iterator = emptyIterator(); -// Iterator removeFrom; -// -// @Override -// public boolean hasNext() { -// if (!iterator.hasNext()) { -// iterator = iterable.iterator(); -// } -// return iterator.hasNext(); -// } -// @Override -// public T next() { -// if (!hasNext()) { -// throw new NoSuchElementException(); -// } -// removeFrom = iterator; -// return iterator.next(); -// } -// @Override -// public void remove() { -// checkRemove(removeFrom != null); -// removeFrom.remove(); -// removeFrom = null; -// } -// }; -// } - - /** - * Returns an iterator that cycles indefinitely over the provided elements. - * - *

The returned iterator supports {@code remove()}. After {@code remove()} - * is called, subsequent cycles omit the removed - * element, but {@code elements} does not change. The iterator's - * {@code hasNext()} method returns {@code true} until all of the original - * elements have been removed. - * - *

Warning: Typical uses of the resulting iterator may produce an - * infinite loop. You should use an explicit {@code break} or be certain that - * you will eventually remove all the elements. - */ -// public static Iterator cycle(T... elements) { -// return cycle(Lists.newArrayList(elements)); -// } - - /** - * Combines two iterators into a single iterator. The returned iterator - * iterates across the elements in {@code a}, followed by the elements in - * {@code b}. The source iterators are not polled until necessary. - * - *

The returned iterator supports {@code remove()} when the corresponding - * input iterator supports it. - * - *

Note: the current implementation is not suitable for nested - * concatenated iterators, i.e. the following should be avoided when in a loop: - * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the - * resulting iterator has a cubic complexity to the depth of the nesting. - */ -// public static Iterator concat(Iterator a, -// Iterator b) { -// return concat(ImmutableList.of(a, b).iterator()); -// } - - /** - * Combines three iterators into a single iterator. The returned iterator - * iterates across the elements in {@code a}, followed by the elements in - * {@code b}, followed by the elements in {@code c}. The source iterators - * are not polled until necessary. - * - *

The returned iterator supports {@code remove()} when the corresponding - * input iterator supports it. - * - *

Note: the current implementation is not suitable for nested - * concatenated iterators, i.e. the following should be avoided when in a loop: - * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the - * resulting iterator has a cubic complexity to the depth of the nesting. - */ -// public static Iterator concat(Iterator a, -// Iterator b, Iterator c) { -// return concat(ImmutableList.of(a, b, c).iterator()); -// } - - /** - * Combines four iterators into a single iterator. The returned iterator - * iterates across the elements in {@code a}, followed by the elements in - * {@code b}, followed by the elements in {@code c}, followed by the elements - * in {@code d}. The source iterators are not polled until necessary. - * - *

The returned iterator supports {@code remove()} when the corresponding - * input iterator supports it. - * - *

Note: the current implementation is not suitable for nested - * concatenated iterators, i.e. the following should be avoided when in a loop: - * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the - * resulting iterator has a cubic complexity to the depth of the nesting. - */ -// public static Iterator concat(Iterator a, -// Iterator b, Iterator c, -// Iterator d) { -// return concat(ImmutableList.of(a, b, c, d).iterator()); -// } - - /** - * Combines multiple iterators into a single iterator. The returned iterator - * iterates across the elements of each iterator in {@code inputs}. The input - * iterators are not polled until necessary. - * - *

The returned iterator supports {@code remove()} when the corresponding - * input iterator supports it. - * - *

Note: the current implementation is not suitable for nested - * concatenated iterators, i.e. the following should be avoided when in a loop: - * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the - * resulting iterator has a cubic complexity to the depth of the nesting. - * - * @throws NullPointerException if any of the provided iterators is null - */ -// public static Iterator concat(Iterator... inputs) { -// return concat(ImmutableList.copyOf(inputs).iterator()); -// } - - /** - * Combines multiple iterators into a single iterator. The returned iterator - * iterates across the elements of each iterator in {@code inputs}. The input - * iterators are not polled until necessary. - * - *

The returned iterator supports {@code remove()} when the corresponding - * input iterator supports it. The methods of the returned iterator may throw - * {@code NullPointerException} if any of the input iterators is null. - * - *

Note: the current implementation is not suitable for nested - * concatenated iterators, i.e. the following should be avoided when in a loop: - * {@code iterator = Iterators.concat(iterator, suffix);}, since iteration over the - * resulting iterator has a cubic complexity to the depth of the nesting. - */ -// public static Iterator concat( -// final Iterator> inputs) { -// checkNotNull(inputs); -// return new Iterator() { -// Iterator current = emptyIterator(); -// Iterator removeFrom; -// -// @Override -// public boolean hasNext() { -// // http://code.google.com/p/google-collections/issues/detail?id=151 -// // current.hasNext() might be relatively expensive, worth minimizing. -// boolean currentHasNext; -// // checkNotNull eager for GWT -// // note: it must be here & not where 'current' is assigned, -// // because otherwise we'll have called inputs.next() before throwing -// // the first NPE, and the next time around we'll call inputs.next() -// // again, incorrectly moving beyond the error. -// while (!(currentHasNext = checkNotNull(current).hasNext()) -// && inputs.hasNext()) { -// current = inputs.next(); -// } -// return currentHasNext; -// } -// @Override -// public T next() { -// if (!hasNext()) { -// throw new NoSuchElementException(); -// } -// removeFrom = current; -// return current.next(); -// } -// @Override -// public void remove() { -// checkRemove(removeFrom != null); -// removeFrom.remove(); -// removeFrom = null; -// } -// }; -// } - - /** - * Divides an iterator into unmodifiable sublists of the given size (the final - * list may be smaller). For example, partitioning an iterator containing - * {@code [a, b, c, d, e]} with a partition size of 3 yields {@code - * [[a, b, c], [d, e]]} -- an outer iterator containing two inner lists of - * three and two elements, all in the original order. - * - *

The returned lists implement {@link java.util.RandomAccess}. - * - * @param iterator the iterator to return a partitioned view of - * @param size the desired size of each partition (the last may be smaller) - * @return an iterator of immutable lists containing the elements of {@code - * iterator} divided into partitions - * @throws IllegalArgumentException if {@code size} is nonpositive - */ -// public static UnmodifiableIterator> partition( -// Iterator iterator, int size) { -// return partitionImpl(iterator, size, false); -// } - - /** - * Divides an iterator into unmodifiable sublists of the given size, padding - * the final iterator with null values if necessary. For example, partitioning - * an iterator containing {@code [a, b, c, d, e]} with a partition size of 3 - * yields {@code [[a, b, c], [d, e, null]]} -- an outer iterator containing - * two inner lists of three elements each, all in the original order. - * - *

The returned lists implement {@link java.util.RandomAccess}. - * - * @param iterator the iterator to return a partitioned view of - * @param size the desired size of each partition - * @return an iterator of immutable lists containing the elements of {@code - * iterator} divided into partitions (the final iterable may have - * trailing null elements) - * @throws IllegalArgumentException if {@code size} is nonpositive - */ -// public static UnmodifiableIterator> paddedPartition( -// Iterator iterator, int size) { -// return partitionImpl(iterator, size, true); -// } - -// private static UnmodifiableIterator> partitionImpl( -// final Iterator iterator, final int size, final boolean pad) { -// checkNotNull(iterator); -// checkArgument(size > 0); -// return new UnmodifiableIterator>() { -// @Override -// public boolean hasNext() { -// return iterator.hasNext(); -// } -// @Override -// public List next() { -// if (!hasNext()) { -// throw new NoSuchElementException(); -// } -// Object[] array = new Object[size]; -// int count = 0; -// for (; count < size && iterator.hasNext(); count++) { -// array[count] = iterator.next(); -// } -// for (int i = count; i < size; i++) { -// array[i] = null; // for GWT -// } -// -// // we only put Ts in it -// List list = Collections.unmodifiableList( -// (List) Arrays.asList(array)); -// return (pad || count == size) ? list : list.subList(0, count); -// } -// }; -// } - - /** - * Returns the elements of {@code unfiltered} that satisfy a predicate. - */ - public static UnmodifiableIterator filter( - final Iterator unfiltered, final Predicate predicate) { - checkNotNull(unfiltered); - checkNotNull(predicate); - return new AbstractIterator() { - @Override protected T computeNext() { - while (unfiltered.hasNext()) { - T element = unfiltered.next(); - if (predicate.test(element)) { - return element; - } - } - return endOfData(); - } - }; - } - - /** - * Returns all instances of class {@code type} in {@code unfiltered}. The - * returned iterator has elements whose class is {@code type} or a subclass of - * {@code type}. - * - * @param unfiltered an iterator containing objects of any type - * @param type the type of elements desired - * @return an unmodifiable iterator containing all elements of the original - * iterator that were of the requested type - */ - // can cast to because non-Ts are removed - - public static UnmodifiableIterator filter( - Iterator unfiltered, Class type) { - return (UnmodifiableIterator) filter(unfiltered, instanceOf(type)); - } - - /** - * Returns {@code true} if one or more elements returned by {@code iterator} - * satisfy the given predicate. - */ - public static boolean any( - Iterator iterator, Predicate predicate) { - return indexOf(iterator, predicate) != -1; - } - - /** - * Returns {@code true} if every element returned by {@code iterator} - * satisfies the given predicate. If {@code iterator} is empty, {@code true} - * is returned. - */ - public static boolean all( - Iterator iterator, Predicate predicate) { - checkNotNull(predicate); - while (iterator.hasNext()) { - T element = iterator.next(); - if (!predicate.test(element)) { - return false; - } - } - return true; - } - - /** - * Returns the first element in {@code iterator} that satisfies the given - * predicate; use this method only when such an element is known to exist. If - * no such element is found, the iterator will be left exhausted: its {@code - * hasNext()} method will return {@code false}. If it is possible that - * no element will match, use {@link #tryFind} or {@link - * #find(Iterator, Predicate, Object)} instead. - * - * @throws NoSuchElementException if no element in {@code iterator} matches - * the given predicate - */ -// public static T find( -// Iterator iterator, Predicate predicate) { -// return filter(iterator, predicate).next(); -// } - - /** - * Returns the first element in {@code iterator} that satisfies the given - * predicate. If no such element is found, {@code defaultValue} will be - * returned from this method and the iterator will be left exhausted: its - * {@code hasNext()} method will return {@code false}. Note that this can - * usually be handled more naturally using {@code - * tryFind(iterator, predicate).or(defaultValue)}. - * - * @since 7.0 - */ -// -// public static T find(Iterator iterator, Predicate predicate, -// T defaultValue) { -// return getNext(filter(iterator, predicate), defaultValue); -// } - - /** - * Returns an {@link Optional} containing the first element in {@code - * iterator} that satisfies the given predicate, if such an element exists. If - * no such element is found, an empty {@link Optional} will be returned from - * this method and the iterator will be left exhausted: its {@code - * hasNext()} method will return {@code false}. - * - *

Warning: avoid using a {@code predicate} that matches {@code - * null}. If {@code null} is matched in {@code iterator}, a - * NullPointerException will be thrown. - * - * @since 11.0 - */ -// public static Optional tryFind( -// Iterator iterator, Predicate predicate) { -// UnmodifiableIterator filteredIterator = filter(iterator, predicate); -// return filteredIterator.hasNext() -// ? Optional.of(filteredIterator.next()) -// : Optional.absent(); -// } - - /** - * Returns the index in {@code iterator} of the first element that satisfies - * the provided {@code predicate}, or {@code -1} if the Iterator has no such - * elements. - * - *

More formally, returns the lowest index {@code i} such that - * {@code predicate.apply(Iterators.get(iterator, i))} returns {@code true}, - * or {@code -1} if there is no such index. - * - *

If -1 is returned, the iterator will be left exhausted: its - * {@code hasNext()} method will return {@code false}. Otherwise, - * the iterator will be set to the element which satisfies the - * {@code predicate}. - * - * @since 2.0 - */ - public static int indexOf( - Iterator iterator, Predicate predicate) { - checkNotNull(predicate, "predicate"); - for (int i = 0; iterator.hasNext(); i++) { - T current = iterator.next(); - if (predicate.test(current)) { - return i; - } - } - return -1; - } - - /** - * Returns an iterator that applies {@code function} to each element of {@code - * fromIterator}. - * - *

The returned iterator supports {@code remove()} if the provided iterator - * does. After a successful {@code remove()} call, {@code fromIterator} no - * longer contains the corresponding element. - */ - public static Iterator transform(final Iterator fromIterator, - final Function function) { - checkNotNull(function); - return new TransformedIterator(fromIterator) { - @Override - T transform(F from) { - return function.apply(from); - } - }; - } - - /** - * Advances {@code iterator} {@code position + 1} times, returning the - * element at the {@code position}th position. - * - * @param position position of the element to return - * @return the element at the specified position in {@code iterator} - * @throws IndexOutOfBoundsException if {@code position} is negative or - * greater than or equal to the number of elements remaining in - * {@code iterator} - */ -// public static T get(Iterator iterator, int position) { -// checkNonnegative(position); -// int skipped = advance(iterator, position); -// if (!iterator.hasNext()) { -// throw new IndexOutOfBoundsException("position (" + position -// + ") must be less than the number of elements that remained (" -// + skipped + ")"); -// } -// return iterator.next(); -// } - -// static void checkNonnegative(int position) { -// if (position < 0) { -// throw new IndexOutOfBoundsException("position (" + position -// + ") must not be negative"); -// } -// } - - /** - * Advances {@code iterator} {@code position + 1} times, returning the - * element at the {@code position}th position or {@code defaultValue} - * otherwise. - * - * @param position position of the element to return - * @param defaultValue the default value to return if the iterator is empty - * or if {@code position} is greater than the number of elements - * remaining in {@code iterator} - * @return the element at the specified position in {@code iterator} or - * {@code defaultValue} if {@code iterator} produces fewer than - * {@code position + 1} elements. - * @throws IndexOutOfBoundsException if {@code position} is negative - * @since 4.0 - */ -// -// public static T get(Iterator iterator, int position, T defaultValue) { -// checkNonnegative(position); -// advance(iterator, position); -// return getNext(iterator, defaultValue); -// } - - /** - * Returns the next element in {@code iterator} or {@code defaultValue} if - * the iterator is empty. The {@link Iterables} analog to this method is - * {@link Iterables#getFirst}. - * - * @param defaultValue the default value to return if the iterator is empty - * @return the next element of {@code iterator} or the default value - * @since 7.0 - */ -// -// public static T getNext(Iterator iterator, T defaultValue) { -// return iterator.hasNext() ? iterator.next() : defaultValue; -// } - - /** - * Advances {@code iterator} to the end, returning the last element. - * - * @return the last element of {@code iterator} - * @throws NoSuchElementException if the iterator is empty - */ -// public static T getLast(Iterator iterator) { -// while (true) { -// T current = iterator.next(); -// if (!iterator.hasNext()) { -// return current; -// } -// } -// } - - /** - * Advances {@code iterator} to the end, returning the last element or - * {@code defaultValue} if the iterator is empty. - * - * @param defaultValue the default value to return if the iterator is empty - * @return the last element of {@code iterator} - * @since 3.0 - */ -// -// public static T getLast(Iterator iterator, T defaultValue) { -// return iterator.hasNext() ? getLast(iterator) : defaultValue; -// } - - /** - * Calls {@code next()} on {@code iterator}, either {@code numberToAdvance} times - * or until {@code hasNext()} returns {@code false}, whichever comes first. - * - * @return the number of elements the iterator was advanced - * @since 13.0 (since 3.0 as {@code Iterators.skip}) - */ -// public static int advance(Iterator iterator, int numberToAdvance) { -// checkNotNull(iterator); -// checkArgument(numberToAdvance >= 0, "numberToAdvance must be nonnegative"); -// -// int i; -// for (i = 0; i < numberToAdvance && iterator.hasNext(); i++) { -// iterator.next(); -// } -// return i; -// } - - /** - * Creates an iterator returning the first {@code limitSize} elements of the - * given iterator. If the original iterator does not contain that many - * elements, the returned iterator will have the same behavior as the original - * iterator. The returned iterator supports {@code remove()} if the original - * iterator does. - * - * @param iterator the iterator to limit - * @param limitSize the maximum number of elements in the returned iterator - * @throws IllegalArgumentException if {@code limitSize} is negative - * @since 3.0 - */ -// public static Iterator limit( -// final Iterator iterator, final int limitSize) { -// checkNotNull(iterator); -// checkArgument(limitSize >= 0, "limit is negative"); -// return new Iterator() { -// private int count; -// -// @Override -// public boolean hasNext() { -// return count < limitSize && iterator.hasNext(); -// } -// -// @Override -// public T next() { -// if (!hasNext()) { -// throw new NoSuchElementException(); -// } -// count++; -// return iterator.next(); -// } -// -// @Override -// public void remove() { -// iterator.remove(); -// } -// }; -// } - - /** - * Returns a view of the supplied {@code iterator} that removes each element - * from the supplied {@code iterator} as it is returned. - * - *

The provided iterator must support {@link Iterator#remove()} or - * else the returned iterator will fail on the first call to {@code - * next}. - * - * @param iterator the iterator to remove and return elements from - * @return an iterator that removes and returns elements from the - * supplied iterator - * @since 2.0 - */ -// public static Iterator consumingIterator(final Iterator iterator) { -// checkNotNull(iterator); -// return new UnmodifiableIterator() { -// @Override -// public boolean hasNext() { -// return iterator.hasNext(); -// } -// -// @Override -// public T next() { -// T next = iterator.next(); -// iterator.remove(); -// return next; -// } -// -// @Override -// public String toString() { -// return "Iterators.consumingIterator(...)"; -// } -// }; -// } - - /** - * Deletes and returns the next value from the iterator, or returns - * {@code null} if there is no such value. - */ -// -// static T pollNext(Iterator iterator) { -// if (iterator.hasNext()) { -// T result = iterator.next(); -// iterator.remove(); -// return result; -// } else { -// return null; -// } -// } - - // Methods only in Iterators, not in Iterables - - /** - * Clears the iterator using its remove method. - */ - static void clear(Iterator iterator) { - checkNotNull(iterator); - while (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - /** - * Returns an iterator containing the elements of {@code array} in order. The - * returned iterator is a view of the array; subsequent changes to the array - * will be reflected in the iterator. - * - *

Note: It is often preferable to represent your data using a - * collection type, for example using {@link Arrays#asList(Object[])}, making - * this method unnecessary. - * - *

The {@code Iterable} equivalent of this method is either {@link - * Arrays#asList(Object[])}, {@link ImmutableList#copyOf(Object[])}}, - * or {@link ImmutableList#of}. - */ - public static UnmodifiableIterator forArray(final T... array) { - return forArray(array, 0, array.length, 0); - } - - /** - * Returns a list iterator containing the elements in the specified range of - * {@code array} in order, starting at the specified index. - * - *

The {@code Iterable} equivalent of this method is {@code - * Arrays.asList(array).subList(offset, offset + length).listIterator(index)}. - */ - static UnmodifiableListIterator forArray( - final T[] array, final int offset, int length, int index) { - checkArgument(length >= 0); - int end = offset + length; - - // Technically we should give a slightly more descriptive error on overflow - Preconditions.checkPositionIndexes(offset, end, array.length); - Preconditions.checkPositionIndex(index, length); - if (length == 0) { - return emptyListIterator(); - } - - /* - * We can't use call the two-arg constructor with arguments (offset, end) - * because the returned Iterator is a ListIterator that may be moved back - * past the beginning of the iteration. - */ - return new AbstractIndexedListIterator(length, index) { - @Override protected T get(int index) { - return array[offset + index]; - } - }; - } - - /** - * Returns an iterator containing only {@code value}. - * - *

The {@link Iterable} equivalent of this method is {@link - * Collections#singleton}. - */ -// public static UnmodifiableIterator singletonIterator( -// final T value) { -// return new UnmodifiableIterator() { -// boolean done; -// @Override -// public boolean hasNext() { -// return !done; -// } -// @Override -// public T next() { -// if (done) { -// throw new NoSuchElementException(); -// } -// done = true; -// return value; -// } -// }; -// } - - /** - * Adapts an {@code Enumeration} to the {@code Iterator} interface. - * - *

This method has no equivalent in {@link Iterables} because viewing an - * {@code Enumeration} as an {@code Iterable} is impossible. However, the - * contents can be copied into a collection using {@link - * Collections#list}. - */ -// public static UnmodifiableIterator forEnumeration( -// final Enumeration enumeration) { -// checkNotNull(enumeration); -// return new UnmodifiableIterator() { -// @Override -// public boolean hasNext() { -// return enumeration.hasMoreElements(); -// } -// @Override -// public T next() { -// return enumeration.nextElement(); -// } -// }; -// } - - /** - * Adapts an {@code Iterator} to the {@code Enumeration} interface. - * - *

The {@code Iterable} equivalent of this method is either {@link - * Collections#enumeration} (if you have a {@link Collection}), or - * {@code Iterators.asEnumeration(collection.iterator())}. - */ -// public static Enumeration asEnumeration(final Iterator iterator) { -// checkNotNull(iterator); -// return new Enumeration() { -// @Override -// public boolean hasMoreElements() { -// return iterator.hasNext(); -// } -// @Override -// public T nextElement() { -// return iterator.next(); -// } -// }; -// } - - /** - * Implementation of PeekingIterator that avoids peeking unless necessary. - */ -// private static class PeekingImpl implements PeekingIterator { -// -// private final Iterator iterator; -// private boolean hasPeeked; -// private E peekedElement; -// -// public PeekingImpl(Iterator iterator) { -// this.iterator = checkNotNull(iterator); -// } -// -// @Override -// public boolean hasNext() { -// return hasPeeked || iterator.hasNext(); -// } -// -// @Override -// public E next() { -// if (!hasPeeked) { -// return iterator.next(); -// } -// E result = peekedElement; -// hasPeeked = false; -// peekedElement = null; -// return result; -// } -// -// @Override -// public void remove() { -// checkState(!hasPeeked, "Can't remove after you've peeked at next"); -// iterator.remove(); -// } -// -// @Override -// public E peek() { -// if (!hasPeeked) { -// peekedElement = iterator.next(); -// hasPeeked = true; -// } -// return peekedElement; -// } -// } - - /** - * Returns a {@code PeekingIterator} backed by the given iterator. - * - *

Calls to the {@code peek} method with no intervening calls to {@code - * next} do not affect the iteration, and hence return the same object each - * time. A subsequent call to {@code next} is guaranteed to return the same - * object again. For example:

   {@code
-   *
-   *   PeekingIterator peekingIterator =
-   *       Iterators.peekingIterator(Iterators.forArray("a", "b"));
-   *   String a1 = peekingIterator.peek(); // returns "a"
-   *   String a2 = peekingIterator.peek(); // also returns "a"
-   *   String a3 = peekingIterator.next(); // also returns "a"}
- * - *

Any structural changes to the underlying iteration (aside from those - * performed by the iterator's own {@link PeekingIterator#remove()} method) - * will leave the iterator in an undefined state. - * - *

The returned iterator does not support removal after peeking, as - * explained by {@link PeekingIterator#remove()}. - * - *

Note: If the given iterator is already a {@code PeekingIterator}, - * it might be returned to the caller, although this is neither - * guaranteed to occur nor required to be consistent. For example, this - * method might choose to pass through recognized implementations of - * {@code PeekingIterator} when the behavior of the implementation is - * known to meet the contract guaranteed by this method. - * - *

There is no {@link Iterable} equivalent to this method, so use this - * method to wrap each individual iterator as it is generated. - * - * @param iterator the backing iterator. The {@link PeekingIterator} assumes - * ownership of this iterator, so users should cease making direct calls - * to it after calling this method. - * @return a peeking iterator backed by that iterator. Apart from the - * additional {@link PeekingIterator#peek()} method, this iterator behaves - * exactly the same as {@code iterator}. - */ -// public static PeekingIterator peekingIterator( -// Iterator iterator) { -// if (iterator instanceof PeekingImpl) { -// // Safe to cast to because PeekingImpl only uses T -// // covariantly (and cannot be subclassed to add non-covariant uses). -// -// PeekingImpl peeking = (PeekingImpl) iterator; -// return peeking; -// } -// return new PeekingImpl(iterator); -// } - - /** - * Simply returns its argument. - * - * @deprecated no need to use this - * @since 10.0 - */ -// @Deprecated public static PeekingIterator peekingIterator( -// PeekingIterator iterator) { -// return checkNotNull(iterator); -// } - - /** - * Returns an iterator over the merged contents of all given - * {@code iterators}, traversing every element of the input iterators. - * Equivalent entries will not be de-duplicated. - * - *

Callers must ensure that the source {@code iterators} are in - * non-descending order as this method does not sort its input. - * - *

For any equivalent elements across all {@code iterators}, it is - * undefined which element is returned first. - * - * @since 11.0 - */ -// @Beta -// public static UnmodifiableIterator mergeSorted( -// Iterable> iterators, -// Comparator comparator) { -// checkNotNull(iterators, "iterators"); -// checkNotNull(comparator, "comparator"); -// -// return new MergingIterator(iterators, comparator); -// } - - /** - * An iterator that performs a lazy N-way merge, calculating the next value - * each time the iterator is polled. This amortizes the sorting cost over the - * iteration and requires less memory than sorting all elements at once. - * - *

Retrieving a single element takes approximately O(log(M)) time, where M - * is the number of iterators. (Retrieving all elements takes approximately - * O(N*log(M)) time, where N is the total number of elements.) - */ -// private static class MergingIterator extends UnmodifiableIterator { -// final Queue> queue; -// -// public MergingIterator(Iterable> iterators, -// final Comparator itemComparator) { -// // A comparator that's used by the heap, allowing the heap -// // to be sorted based on the top of each iterator. -// Comparator> heapComparator = -// new Comparator>() { -// @Override -// public int compare(PeekingIterator o1, PeekingIterator o2) { -// return itemComparator.compare(o1.peek(), o2.peek()); -// } -// }; -// -// queue = new PriorityQueue>(2, heapComparator); -// -// for (Iterator iterator : iterators) { -// if (iterator.hasNext()) { -// queue.add(Iterators.peekingIterator(iterator)); -// } -// } -// } -// -// @Override -// public boolean hasNext() { -// return !queue.isEmpty(); -// } -// -// @Override -// public T next() { -// PeekingIterator nextIter = queue.remove(); -// T next = nextIter.next(); -// if (nextIter.hasNext()) { -// queue.add(nextIter); -// } -// return next; -// } -// } - - /** - * Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 - */ - static ListIterator cast(Iterator iterator) { - return (ListIterator) iterator; - } -} diff --git a/java/src/game/collect/Lists.java b/java/src/game/collect/Lists.java deleted file mode 100644 index ed6b25b..0000000 --- a/java/src/game/collect/Lists.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; - -public final class Lists { - public static ArrayList newArrayList() { - return new ArrayList(); - } - - public static ArrayList newArrayList(E... elements) { - // Avoid integer overflow when a large array is passed in - int capacity = 5 + elements.length + (elements.length / 10); - ArrayList list = new ArrayList(capacity); - Collections.addAll(list, elements); - return list; - } - - public static ArrayList newArrayList(Iterable elements) { - // Let ArrayList's sizing logic work, if possible - return (elements instanceof Collection) - ? new ArrayList(Filter.cast(elements)) - : newArrayList(elements.iterator()); - } - - public static ArrayList newArrayList(Iterator elements) { - ArrayList list = newArrayList(); - Iterators.addAll(list, elements); - return list; - } -} diff --git a/java/src/game/collect/Maps.java b/java/src/game/collect/Maps.java deleted file mode 100644 index 74ba127..0000000 --- a/java/src/game/collect/Maps.java +++ /dev/null @@ -1,3953 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkNonnegative; -import static game.collect.Preconditions.checkNotNull; -import static game.util.Predicates.compose; - -import java.util.AbstractCollection; -import java.util.AbstractMap; -import java.util.Collection; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Static utility methods pertaining to {@link Map} instances (including instances of - * {@link SortedMap}, {@link BiMap}, etc.). Also see this class's counterparts - * {@link Lists}, {@link Sets} and {@link Queues}. - * - *

See the Guava User Guide article on - * {@code Maps}. - * - * @author Kevin Bourrillion - * @author Mike Bostock - * @author Isaac Shum - * @author Louis Wasserman - * @since 2.0 (imported from Google Collections Library) - */ - -public final class Maps { - private static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2); - - private Maps() {} - - private enum EntryFunction implements Function, Object> { - KEY { - @Override - - public Object apply(Entry entry) { - return entry.getKey(); - } - }, - VALUE { - @Override - - public Object apply(Entry entry) { - return entry.getValue(); - } - }; - } - - - static Function, K> keyFunction() { - return (Function) EntryFunction.KEY; - } - - - static Function, V> valueFunction() { - return (Function) EntryFunction.VALUE; - } - - static Iterator keyIterator(Iterator> entryIterator) { - return Iterators.transform(entryIterator, Maps.keyFunction()); - } - - static Iterator valueIterator(Iterator> entryIterator) { - return Iterators.transform(entryIterator, Maps.valueFunction()); - } - - static UnmodifiableIterator valueIterator( - final UnmodifiableIterator> entryIterator) { - return new UnmodifiableIterator() { - @Override - public boolean hasNext() { - return entryIterator.hasNext(); - } - - @Override - public V next() { - return entryIterator.next().getValue(); - } - }; - } - - /** - * Returns an immutable map instance containing the given entries. - * Internally, the returned map will be backed by an {@link EnumMap}. - * - *

The iteration order of the returned map follows the enum's iteration - * order, not the order in which the elements appear in the given map. - * - * @param map the map to make an immutable copy of - * @return an immutable map containing those entries - * @since 14.0 - */ -// -// @Beta -// public static , V> ImmutableMap immutableEnumMap( -// Map map) { -// if (map instanceof ImmutableEnumMap) { -// // safe covariant cast -// ImmutableEnumMap result = (ImmutableEnumMap) map; -// return result; -// } else if (map.isEmpty()) { -// return ImmutableMap.of(); -// } else { -// for (Map.Entry entry : map.entrySet()) { -// checkNotNull(entry.getKey()); -// checkNotNull(entry.getValue()); -// } -// return ImmutableEnumMap.asImmutable(new EnumMap(map)); -// } -// } - - /** - * Creates a mutable, empty {@code HashMap} instance. - * - *

Note: if mutability is not required, use {@link - * ImmutableMap#of()} instead. - * - *

Note: if {@code K} is an {@code enum} type, use {@link - * #newEnumMap} instead. - * - * @return a new, empty {@code HashMap} - */ - public static HashMap newHashMap() { - return new HashMap(); - } - - /** - * Creates a {@code HashMap} instance, with a high enough "initial capacity" - * that it should hold {@code expectedSize} elements without growth. - * This behavior cannot be broadly guaranteed, but it is observed to be true - * for OpenJDK 1.6. It also can't be guaranteed that the method isn't - * inadvertently oversizing the returned map. - * - * @param expectedSize the number of elements you expect to add to the - * returned map - * @return a new, empty {@code HashMap} with enough capacity to hold {@code - * expectedSize} elements without resizing - * @throws IllegalArgumentException if {@code expectedSize} is negative - */ - public static HashMap newHashMapWithExpectedSize( - int expectedSize) { - return new HashMap(capacity(expectedSize)); - } - - /** - * Returns a capacity that is sufficient to keep the map from being resized as - * long as it grows no larger than expectedSize and the load factor is >= its - * default (0.75). - */ - static int capacity(int expectedSize) { - if (expectedSize < 3) { - checkNonnegative(expectedSize, "expectedSize"); - return expectedSize + 1; - } - if (expectedSize < MAX_POWER_OF_TWO) { - return expectedSize + expectedSize / 3; - } - return Integer.MAX_VALUE; // any large value - } - - /** - * Creates a mutable {@code HashMap} instance with the same mappings as - * the specified map. - * - *

Note: if mutability is not required, use {@link - * ImmutableMap#copyOf(Map)} instead. - * - *

Note: if {@code K} is an {@link Enum} type, use {@link - * #newEnumMap} instead. - * - * @param map the mappings to be placed in the new map - * @return a new {@code HashMap} initialized with the mappings from {@code - * map} - */ - public static HashMap newHashMap( - Map map) { - return new HashMap(map); - } - - /** - * Creates a mutable, empty, insertion-ordered {@code LinkedHashMap} - * instance. - * - *

Note: if mutability is not required, use {@link - * ImmutableMap#of()} instead. - * - * @return a new, empty {@code LinkedHashMap} - */ - public static LinkedHashMap newLinkedHashMap() { - return new LinkedHashMap(); - } - - /** - * Creates a mutable, insertion-ordered {@code LinkedHashMap} instance - * with the same mappings as the specified map. - * - *

Note: if mutability is not required, use {@link - * ImmutableMap#copyOf(Map)} instead. - * - * @param map the mappings to be placed in the new map - * @return a new, {@code LinkedHashMap} initialized with the mappings from - * {@code map} - */ - public static LinkedHashMap newLinkedHashMap( - Map map) { - return new LinkedHashMap(map); - } - - /** - * Returns a general-purpose instance of {@code ConcurrentMap}, which supports - * all optional operations of the ConcurrentMap interface. It does not permit - * null keys or values. It is serializable. - * - *

This is currently accomplished by calling {@link MapMaker#makeMap()}. - * - *

It is preferable to use {@code MapMaker} directly (rather than through - * this method), as it presents numerous useful configuration options, - * such as the concurrency level, load factor, key/value reference types, - * and value computation. - * - * @return a new, empty {@code ConcurrentMap} - * @since 3.0 - */ -// public static ConcurrentMap newConcurrentMap() { -// return new MapMaker().makeMap(); -// } - - /** - * Creates a mutable, empty {@code TreeMap} instance using the natural - * ordering of its elements. - * - *

Note: if mutability is not required, use {@link - * ImmutableSortedMap#of()} instead. - * - * @return a new, empty {@code TreeMap} - */ - public static TreeMap newTreeMap() { - return new TreeMap(); - } - - /** - * Creates a mutable {@code TreeMap} instance with the same mappings as - * the specified map and using the same ordering as the specified map. - * - *

Note: if mutability is not required, use {@link - * ImmutableSortedMap#copyOfSorted(SortedMap)} instead. - * - * @param map the sorted map whose mappings are to be placed in the new map - * and whose comparator is to be used to sort the new map - * @return a new {@code TreeMap} initialized with the mappings from {@code - * map} and using the comparator of {@code map} - */ -// public static TreeMap newTreeMap(SortedMap map) { -// return new TreeMap(map); -// } - - /** - * Creates a mutable, empty {@code TreeMap} instance using the given - * comparator. - * - *

Note: if mutability is not required, use {@code - * ImmutableSortedMap.orderedBy(comparator).build()} instead. - * - * @param comparator the comparator to sort the keys with - * @return a new, empty {@code TreeMap} - */ -// public static TreeMap newTreeMap( -// Comparator comparator) { -// // Ideally, the extra type parameter "C" shouldn't be necessary. It is a -// // work-around of a compiler type inference quirk that prevents the -// // following code from being compiled: -// // Comparator> comparator = null; -// // Map, String> map = newTreeMap(comparator); -// return new TreeMap(comparator); -// } - - /** - * Creates an {@code EnumMap} instance. - * - * @param type the key type for this map - * @return a new, empty {@code EnumMap} - */ - public static , V> EnumMap newEnumMap(Class type) { - return new EnumMap(checkNotNull(type)); - } - - /** - * Creates an {@code EnumMap} with the same mappings as the specified map. - * - * @param map the map from which to initialize this {@code EnumMap} - * @return a new {@code EnumMap} initialized with the mappings from {@code - * map} - * @throws IllegalArgumentException if {@code m} is not an {@code EnumMap} - * instance and contains no mappings - */ -// public static , V> EnumMap newEnumMap( -// Map map) { -// return new EnumMap(map); -// } - - /** - * Creates an {@code IdentityHashMap} instance. - * - * @return a new, empty {@code IdentityHashMap} - */ - public static IdentityHashMap newIdentityHashMap() { - return new IdentityHashMap(); - } - - /** - * Computes the difference between two maps. This difference is an immutable - * snapshot of the state of the maps at the time this method is called. It - * will never change, even if the maps change at a later time. - * - *

Since this method uses {@code HashMap} instances internally, the keys of - * the supplied maps must be well-behaved with respect to - * {@link Object#equals} and {@link Object#hashCode}. - * - *

Note:If you only need to know whether two maps have the same - * mappings, call {@code left.equals(right)} instead of this method. - * - * @param left the map to treat as the "left" map for purposes of comparison - * @param right the map to treat as the "right" map for purposes of comparison - * @return the difference between the two maps - */ -// -// public static MapDifference difference( -// Map left, Map right) { -// if (left instanceof SortedMap) { -// SortedMap sortedLeft = (SortedMap) left; -// SortedMapDifference result = difference(sortedLeft, right); -// return result; -// } -// return difference(left, right, Equivalence.equals()); -// } - - /** - * Computes the difference between two maps. This difference is an immutable - * snapshot of the state of the maps at the time this method is called. It - * will never change, even if the maps change at a later time. - * - *

Values are compared using a provided equivalence, in the case of - * equality, the value on the 'left' is returned in the difference. - * - *

Since this method uses {@code HashMap} instances internally, the keys of - * the supplied maps must be well-behaved with respect to - * {@link Object#equals} and {@link Object#hashCode}. - * - * @param left the map to treat as the "left" map for purposes of comparison - * @param right the map to treat as the "right" map for purposes of comparison - * @param valueEquivalence the equivalence relationship to use to compare - * values - * @return the difference between the two maps - * @since 10.0 - */ -// @Beta -// public static MapDifference difference( -// Map left, Map right, -// Equivalence valueEquivalence) { -// Preconditions.checkNotNull(valueEquivalence); -// -// Map onlyOnLeft = newHashMap(); -// Map onlyOnRight = new HashMap(right); // will whittle it down -// Map onBoth = newHashMap(); -// Map> differences = newHashMap(); -// doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences); -// return new MapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences); -// } -// -// private static void doDifference( -// Map left, Map right, -// Equivalence valueEquivalence, -// Map onlyOnLeft, Map onlyOnRight, Map onBoth, -// Map> differences) { -// for (Entry entry : left.entrySet()) { -// K leftKey = entry.getKey(); -// V leftValue = entry.getValue(); -// if (right.containsKey(leftKey)) { -// V rightValue = onlyOnRight.remove(leftKey); -// if (valueEquivalence.equivalent(leftValue, rightValue)) { -// onBoth.put(leftKey, leftValue); -// } else { -// differences.put( -// leftKey, ValueDifferenceImpl.create(leftValue, rightValue)); -// } -// } else { -// onlyOnLeft.put(leftKey, leftValue); -// } -// } -// } -// -// private static Map unmodifiableMap(Map map) { -// if (map instanceof SortedMap) { -// return Collections.unmodifiableSortedMap((SortedMap) map); -// } else { -// return Collections.unmodifiableMap(map); -// } -// } -// -// static class MapDifferenceImpl implements MapDifference { -// final Map onlyOnLeft; -// final Map onlyOnRight; -// final Map onBoth; -// final Map> differences; -// -// MapDifferenceImpl(Map onlyOnLeft, -// Map onlyOnRight, Map onBoth, -// Map> differences) { -// this.onlyOnLeft = unmodifiableMap(onlyOnLeft); -// this.onlyOnRight = unmodifiableMap(onlyOnRight); -// this.onBoth = unmodifiableMap(onBoth); -// this.differences = unmodifiableMap(differences); -// } -// -// @Override -// public boolean areEqual() { -// return onlyOnLeft.isEmpty() && onlyOnRight.isEmpty() && differences.isEmpty(); -// } -// -// @Override -// public Map entriesOnlyOnLeft() { -// return onlyOnLeft; -// } -// -// @Override -// public Map entriesOnlyOnRight() { -// return onlyOnRight; -// } -// -// @Override -// public Map entriesInCommon() { -// return onBoth; -// } -// -// @Override -// public Map> entriesDiffering() { -// return differences; -// } -// -// @Override public boolean equals(Object object) { -// if (object == this) { -// return true; -// } -// if (object instanceof MapDifference) { -// MapDifference other = (MapDifference) object; -// return entriesOnlyOnLeft().equals(other.entriesOnlyOnLeft()) -// && entriesOnlyOnRight().equals(other.entriesOnlyOnRight()) -// && entriesInCommon().equals(other.entriesInCommon()) -// && entriesDiffering().equals(other.entriesDiffering()); -// } -// return false; -// } -// -// @Override public int hashCode() { -// return Objects.hashCode(entriesOnlyOnLeft(), entriesOnlyOnRight(), -// entriesInCommon(), entriesDiffering()); -// } -// -// @Override public String toString() { -// if (areEqual()) { -// return "equal"; -// } -// -// StringBuilder result = new StringBuilder("not equal"); -// if (!onlyOnLeft.isEmpty()) { -// result.append(": only on left=").append(onlyOnLeft); -// } -// if (!onlyOnRight.isEmpty()) { -// result.append(": only on right=").append(onlyOnRight); -// } -// if (!differences.isEmpty()) { -// result.append(": value differences=").append(differences); -// } -// return result.toString(); -// } -// } -// -// static class ValueDifferenceImpl -// implements MapDifference.ValueDifference { -// private final V left; -// private final V right; -// -// static ValueDifference create(V left, V right) { -// return new ValueDifferenceImpl(left, right); -// } -// -// private ValueDifferenceImpl(V left, V right) { -// this.left = left; -// this.right = right; -// } -// -// @Override -// public V leftValue() { -// return left; -// } -// -// @Override -// public V rightValue() { -// return right; -// } -// -// @Override public boolean equals(Object object) { -// if (object instanceof MapDifference.ValueDifference) { -// MapDifference.ValueDifference that = -// (MapDifference.ValueDifference) object; -// return Objects.equal(this.left, that.leftValue()) -// && Objects.equal(this.right, that.rightValue()); -// } -// return false; -// } -// -// @Override public int hashCode() { -// return Objects.hashCode(left, right); -// } -// -// @Override public String toString() { -// return "(" + left + ", " + right + ")"; -// } -// } -// -// /** -// * Computes the difference between two sorted maps, using the comparator of -// * the left map, or {@code Ordering.natural()} if the left map uses the -// * natural ordering of its elements. This difference is an immutable snapshot -// * of the state of the maps at the time this method is called. It will never -// * change, even if the maps change at a later time. -// * -// *

Since this method uses {@code TreeMap} instances internally, the keys of -// * the right map must all compare as distinct according to the comparator -// * of the left map. -// * -// *

Note:If you only need to know whether two sorted maps have the -// * same mappings, call {@code left.equals(right)} instead of this method. -// * -// * @param left the map to treat as the "left" map for purposes of comparison -// * @param right the map to treat as the "right" map for purposes of comparison -// * @return the difference between the two maps -// * @since 11.0 -// */ -// public static SortedMapDifference difference( -// SortedMap left, Map right) { -// checkNotNull(left); -// checkNotNull(right); -// Comparator comparator = orNaturalOrder(left.comparator()); -// SortedMap onlyOnLeft = Maps.newTreeMap(comparator); -// SortedMap onlyOnRight = Maps.newTreeMap(comparator); -// onlyOnRight.putAll(right); // will whittle it down -// SortedMap onBoth = Maps.newTreeMap(comparator); -// SortedMap> differences = -// Maps.newTreeMap(comparator); -// doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences); -// return new SortedMapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences); -// } -// -// static class SortedMapDifferenceImpl extends MapDifferenceImpl -// implements SortedMapDifference { -// SortedMapDifferenceImpl(SortedMap onlyOnLeft, -// SortedMap onlyOnRight, SortedMap onBoth, -// SortedMap> differences) { -// super(onlyOnLeft, onlyOnRight, onBoth, differences); -// } -// -// @Override public SortedMap> entriesDiffering() { -// return (SortedMap>) super.entriesDiffering(); -// } -// -// @Override public SortedMap entriesInCommon() { -// return (SortedMap) super.entriesInCommon(); -// } -// -// @Override public SortedMap entriesOnlyOnLeft() { -// return (SortedMap) super.entriesOnlyOnLeft(); -// } -// -// @Override public SortedMap entriesOnlyOnRight() { -// return (SortedMap) super.entriesOnlyOnRight(); -// } -// } - - /** - * Returns the specified comparator if not null; otherwise returns {@code - * Ordering.natural()}. This method is an abomination of generics; the only - * purpose of this method is to contain the ugly type-casting in one place. - */ -// -// static Comparator orNaturalOrder( -// Comparator comparator) { -// if (comparator != null) { // can't use ? : because of javac bug 5080917 -// return comparator; -// } -// return (Comparator) Ordering.natural(); -// } - - /** - * Returns a live {@link Map} view whose keys are the contents of {@code set} - * and whose values are computed on demand using {@code function}. To get an - * immutable copy instead, use {@link #toMap(Iterable, Function)}. - * - *

Specifically, for each {@code k} in the backing set, the returned map - * has an entry mapping {@code k} to {@code function.apply(k)}. The {@code - * keySet}, {@code values}, and {@code entrySet} views of the returned map - * iterate in the same order as the backing set. - * - *

Modifications to the backing set are read through to the returned map. - * The returned map supports removal operations if the backing set does. - * Removal operations write through to the backing set. The returned map - * does not support put operations. - * - *

Warning: If the function rejects {@code null}, caution is - * required to make sure the set does not contain {@code null}, because the - * view cannot stop {@code null} from being added to the set. - * - *

Warning: This method assumes that for any instance {@code k} of - * key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also - * of type {@code K}. Using a key type for which this may not hold, such as - * {@code ArrayList}, may risk a {@code ClassCastException} when calling - * methods on the resulting map view. - * - * @since 14.0 - */ -// @Beta -// public static Map asMap( -// Set set, Function function) { -// if (set instanceof SortedSet) { -// return asMap((SortedSet) set, function); -// } else { -// return new AsMapView(set, function); -// } -// } - - /** - * Returns a view of the sorted set as a map, mapping keys from the set - * according to the specified function. - * - *

Specifically, for each {@code k} in the backing set, the returned map - * has an entry mapping {@code k} to {@code function.apply(k)}. The {@code - * keySet}, {@code values}, and {@code entrySet} views of the returned map - * iterate in the same order as the backing set. - * - *

Modifications to the backing set are read through to the returned map. - * The returned map supports removal operations if the backing set does. - * Removal operations write through to the backing set. The returned map does - * not support put operations. - * - *

Warning: If the function rejects {@code null}, caution is - * required to make sure the set does not contain {@code null}, because the - * view cannot stop {@code null} from being added to the set. - * - *

Warning: This method assumes that for any instance {@code k} of - * key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also of - * type {@code K}. Using a key type for which this may not hold, such as - * {@code ArrayList}, may risk a {@code ClassCastException} when calling - * methods on the resulting map view. - * - * @since 14.0 - */ -// @Beta -// public static SortedMap asMap( -// SortedSet set, Function function) { -// return Platform.mapsAsMapSortedSet(set, function); -// } - -// static SortedMap asMapSortedIgnoreNavigable(SortedSet set, -// Function function) { -// return new SortedAsMapView(set, function); -// } - - /** - * Returns a view of the navigable set as a map, mapping keys from the set - * according to the specified function. - * - *

Specifically, for each {@code k} in the backing set, the returned map - * has an entry mapping {@code k} to {@code function.apply(k)}. The {@code - * keySet}, {@code values}, and {@code entrySet} views of the returned map - * iterate in the same order as the backing set. - * - *

Modifications to the backing set are read through to the returned map. - * The returned map supports removal operations if the backing set does. - * Removal operations write through to the backing set. The returned map - * does not support put operations. - * - *

Warning: If the function rejects {@code null}, caution is - * required to make sure the set does not contain {@code null}, because the - * view cannot stop {@code null} from being added to the set. - * - *

Warning: This method assumes that for any instance {@code k} of - * key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also - * of type {@code K}. Using a key type for which this may not hold, such as - * {@code ArrayList}, may risk a {@code ClassCastException} when calling - * methods on the resulting map view. - * - * @since 14.0 - */ -// @Beta -// -// public static NavigableMap asMap( -// NavigableSet set, Function function) { -// return new NavigableAsMapView(set, function); -// } - -// private static class AsMapView extends ImprovedAbstractMap { -// -// private final Set set; -// final Function function; -// -// Set backingSet() { -// return set; -// } -// -// AsMapView(Set set, Function function) { -// this.set = checkNotNull(set); -// this.function = checkNotNull(function); -// } -// -// @Override -// public Set createKeySet() { -// return removeOnlySet(backingSet()); -// } -// -// @Override -// Collection createValues() { -// return Collections2.transform(set, function); -// } -// -// @Override -// public int size() { -// return backingSet().size(); -// } -// -// @Override -// public boolean containsKey(Object key) { -// return backingSet().contains(key); -// } -// -// @Override -// public V get(Object key) { -// if (Collections2.safeContains(backingSet(), key)) { -// // unsafe, but Javadoc warns about it -// K k = (K) key; -// return function.apply(k); -// } else { -// return null; -// } -// } -// -// @Override -// public V remove(Object key) { -// if (backingSet().remove(key)) { -// // unsafe, but Javadoc warns about it -// K k = (K) key; -// return function.apply(k); -// } else { -// return null; -// } -// } -// -// @Override -// public void clear() { -// backingSet().clear(); -// } -// -// @Override -// protected Set> createEntrySet() { -// return new EntrySet() { -// @Override -// Map map() { -// return AsMapView.this; -// } -// -// @Override -// public Iterator> iterator() { -// return asMapEntryIterator(backingSet(), function); -// } -// }; -// } -// } - - static Iterator> asMapEntryIterator( - Set set, final Function function) { - return new TransformedIterator>(set.iterator()) { - @Override - Entry transform(final K key) { - return immutableEntry(key, function.apply(key)); - } - }; - } - -// private static class SortedAsMapView extends AsMapView -// implements SortedMap { -// -// SortedAsMapView(SortedSet set, Function function) { -// super(set, function); -// } -// -// @Override -// SortedSet backingSet() { -// return (SortedSet) super.backingSet(); -// } -// -// @Override -// public Comparator comparator() { -// return backingSet().comparator(); -// } -// -// @Override -// public Set keySet() { -// return removeOnlySortedSet(backingSet()); -// } -// -// @Override -// public SortedMap subMap(K fromKey, K toKey) { -// return asMap(backingSet().subSet(fromKey, toKey), function); -// } -// -// @Override -// public SortedMap headMap(K toKey) { -// return asMap(backingSet().headSet(toKey), function); -// } -// -// @Override -// public SortedMap tailMap(K fromKey) { -// return asMap(backingSet().tailSet(fromKey), function); -// } -// -// @Override -// public K firstKey() { -// return backingSet().first(); -// } -// -// @Override -// public K lastKey() { -// return backingSet().last(); -// } -// } - -// -// private static final class NavigableAsMapView -// extends AbstractNavigableMap { -// /* -// * Using AbstractNavigableMap is simpler than extending SortedAsMapView and rewriting all the -// * NavigableMap methods. -// */ -// -// private final NavigableSet set; -// private final Function function; -// -// NavigableAsMapView(NavigableSet ks, Function vFunction) { -// this.set = checkNotNull(ks); -// this.function = checkNotNull(vFunction); -// } -// -// @Override -// public NavigableMap subMap( -// K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { -// return asMap(set.subSet(fromKey, fromInclusive, toKey, toInclusive), function); -// } -// -// @Override -// public NavigableMap headMap(K toKey, boolean inclusive) { -// return asMap(set.headSet(toKey, inclusive), function); -// } -// -// @Override -// public NavigableMap tailMap(K fromKey, boolean inclusive) { -// return asMap(set.tailSet(fromKey, inclusive), function); -// } -// -// @Override -// public Comparator comparator() { -// return set.comparator(); -// } -// -// @Override -// -// public V get(Object key) { -// if (Collections2.safeContains(set, key)) { -// // unsafe, but Javadoc warns about it -// K k = (K) key; -// return function.apply(k); -// } else { -// return null; -// } -// } -// -// @Override -// public void clear() { -// set.clear(); -// } -// -// @Override -// Iterator> entryIterator() { -// return asMapEntryIterator(set, function); -// } -// -// @Override -// Iterator> descendingEntryIterator() { -// return descendingMap().entrySet().iterator(); -// } -// -// @Override -// public NavigableSet navigableKeySet() { -// return removeOnlyNavigableSet(set); -// } -// -// @Override -// public int size() { -// return set.size(); -// } -// -// @Override -// public NavigableMap descendingMap() { -// return asMap(set.descendingSet(), function); -// } -// } - -// private static Set removeOnlySet(final Set set) { -// return new ForwardingSet() { -// @Override -// protected Set delegate() { -// return set; -// } -// -// @Override -// public boolean add(E element) { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public boolean addAll(Collection es) { -// throw new UnsupportedOperationException(); -// } -// }; -// } - -// private static SortedSet removeOnlySortedSet(final SortedSet set) { -// return new ForwardingSortedSet() { -// @Override -// protected SortedSet delegate() { -// return set; -// } -// -// @Override -// public boolean add(E element) { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public boolean addAll(Collection es) { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public SortedSet headSet(E toElement) { -// return removeOnlySortedSet(super.headSet(toElement)); -// } -// -// @Override -// public SortedSet subSet(E fromElement, E toElement) { -// return removeOnlySortedSet(super.subSet(fromElement, toElement)); -// } -// -// @Override -// public SortedSet tailSet(E fromElement) { -// return removeOnlySortedSet(super.tailSet(fromElement)); -// } -// }; -// } - -// -// private static NavigableSet removeOnlyNavigableSet(final NavigableSet set) { -// return new ForwardingNavigableSet() { -// @Override -// protected NavigableSet delegate() { -// return set; -// } -// -// @Override -// public boolean add(E element) { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public boolean addAll(Collection es) { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public SortedSet headSet(E toElement) { -// return removeOnlySortedSet(super.headSet(toElement)); -// } -// -// @Override -// public SortedSet subSet(E fromElement, E toElement) { -// return removeOnlySortedSet( -// super.subSet(fromElement, toElement)); -// } -// -// @Override -// public SortedSet tailSet(E fromElement) { -// return removeOnlySortedSet(super.tailSet(fromElement)); -// } -// -// @Override -// public NavigableSet headSet(E toElement, boolean inclusive) { -// return removeOnlyNavigableSet(super.headSet(toElement, inclusive)); -// } -// -// @Override -// public NavigableSet tailSet(E fromElement, boolean inclusive) { -// return removeOnlyNavigableSet(super.tailSet(fromElement, inclusive)); -// } -// -// @Override -// public NavigableSet subSet(E fromElement, boolean fromInclusive, -// E toElement, boolean toInclusive) { -// return removeOnlyNavigableSet(super.subSet( -// fromElement, fromInclusive, toElement, toInclusive)); -// } -// -// @Override -// public NavigableSet descendingSet() { -// return removeOnlyNavigableSet(super.descendingSet()); -// } -// }; -// } - - /** - * Returns an immutable map whose keys are the distinct elements of {@code - * keys} and whose value for each key was computed by {@code valueFunction}. - * The map's iteration order is the order of the first appearance of each key - * in {@code keys}. - * - *

If {@code keys} is a {@link Set}, a live view can be obtained instead of - * a copy using {@link Maps#asMap(Set, Function)}. - * - * @throws NullPointerException if any element of {@code keys} is - * {@code null}, or if {@code valueFunction} produces {@code null} - * for any key - * @since 14.0 - */ -// @Beta -// public static ImmutableMap toMap(Iterable keys, -// Function valueFunction) { -// return toMap(keys.iterator(), valueFunction); -// } - - /** - * Returns an immutable map whose keys are the distinct elements of {@code - * keys} and whose value for each key was computed by {@code valueFunction}. - * The map's iteration order is the order of the first appearance of each key - * in {@code keys}. - * - * @throws NullPointerException if any element of {@code keys} is - * {@code null}, or if {@code valueFunction} produces {@code null} - * for any key - * @since 14.0 - */ -// @Beta -// public static ImmutableMap toMap(Iterator keys, -// Function valueFunction) { -// checkNotNull(valueFunction); -// // Using LHM instead of a builder so as not to fail on duplicate keys -// Map builder = newLinkedHashMap(); -// while (keys.hasNext()) { -// K key = keys.next(); -// builder.put(key, valueFunction.apply(key)); -// } -// return ImmutableMap.copyOf(builder); -// } - - /** - * Returns an immutable map for which the {@link Map#values} are the given - * elements in the given order, and each key is the product of invoking a - * supplied function on its corresponding value. - * - * @param values the values to use when constructing the {@code Map} - * @param keyFunction the function used to produce the key for each value - * @return a map mapping the result of evaluating the function {@code - * keyFunction} on each value in the input collection to that value - * @throws IllegalArgumentException if {@code keyFunction} produces the same - * key for more than one value in the input collection - * @throws NullPointerException if any elements of {@code values} is null, or - * if {@code keyFunction} produces {@code null} for any value - */ -// public static ImmutableMap uniqueIndex( -// Iterable values, Function keyFunction) { -// return uniqueIndex(values.iterator(), keyFunction); -// } - - /** - * Returns an immutable map for which the {@link Map#values} are the given - * elements in the given order, and each key is the product of invoking a - * supplied function on its corresponding value. - * - * @param values the values to use when constructing the {@code Map} - * @param keyFunction the function used to produce the key for each value - * @return a map mapping the result of evaluating the function {@code - * keyFunction} on each value in the input collection to that value - * @throws IllegalArgumentException if {@code keyFunction} produces the same - * key for more than one value in the input collection - * @throws NullPointerException if any elements of {@code values} is null, or - * if {@code keyFunction} produces {@code null} for any value - * @since 10.0 - */ -// public static ImmutableMap uniqueIndex( -// Iterator values, Function keyFunction) { -// checkNotNull(keyFunction); -// ImmutableMap.Builder builder = ImmutableMap.builder(); -// while (values.hasNext()) { -// V value = values.next(); -// builder.put(keyFunction.apply(value), value); -// } -// return builder.build(); -// } - - /** - * Creates an {@code ImmutableMap} from a {@code Properties} - * instance. Properties normally derive from {@code Map}, but - * they typically contain strings, which is awkward. This method lets you get - * a plain-old-{@code Map} out of a {@code Properties}. - * - * @param properties a {@code Properties} object to be converted - * @return an immutable map containing all the entries in {@code properties} - * @throws ClassCastException if any key in {@code Properties} is not a {@code - * String} - * @throws NullPointerException if any key or value in {@code Properties} is - * null - */ -// -// public static ImmutableMap fromProperties( -// Properties properties) { -// ImmutableMap.Builder builder = ImmutableMap.builder(); -// -// for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { -// String key = (String) e.nextElement(); -// builder.put(key, properties.getProperty(key)); -// } -// -// return builder.build(); -// } - - /** - * Returns an immutable map entry with the specified key and value. The {@link - * Entry#setValue} operation throws an {@link UnsupportedOperationException}. - * - *

The returned entry is serializable. - * - * @param key the key to be associated with the returned entry - * @param value the value to be associated with the returned entry - */ - - public static Entry immutableEntry( - K key, V value) { - return new ImmutableEntry(key, value); - } - - /** - * Returns an unmodifiable view of the specified set of entries. The {@link - * Entry#setValue} operation throws an {@link UnsupportedOperationException}, - * as do any operations that would modify the returned set. - * - * @param entrySet the entries for which to return an unmodifiable view - * @return an unmodifiable view of the entries - */ -// static Set> unmodifiableEntrySet( -// Set> entrySet) { -// return new UnmodifiableEntrySet( -// Collections.unmodifiableSet(entrySet)); -// } - - /** - * Returns an unmodifiable view of the specified map entry. The {@link - * Entry#setValue} operation throws an {@link UnsupportedOperationException}. - * This also has the side-effect of redefining {@code equals} to comply with - * the Entry contract, to avoid a possible nefarious implementation of equals. - * - * @param entry the entry for which to return an unmodifiable view - * @return an unmodifiable view of the entry - */ - static Entry unmodifiableEntry(final Entry entry) { - checkNotNull(entry); - return new AbstractMapEntry() { - @Override public K getKey() { - return entry.getKey(); - } - - @Override public V getValue() { - return entry.getValue(); - } - }; - } - - /** @see Multimaps#unmodifiableEntries */ - static class UnmodifiableEntries - extends ForwardingCollection> { - private final Collection> entries; - - UnmodifiableEntries(Collection> entries) { - this.entries = entries; - } - - @Override protected Collection> delegate() { - return entries; - } - - @Override public Iterator> iterator() { - final Iterator> delegate = super.iterator(); - return new UnmodifiableIterator>() { - @Override - public boolean hasNext() { - return delegate.hasNext(); - } - - @Override public Entry next() { - return unmodifiableEntry(delegate.next()); - } - }; - } - - // See java.util.Collections.UnmodifiableEntrySet for details on attacks. - - @Override public Object[] toArray() { - return standardToArray(); - } - - @Override public T[] toArray(T[] array) { - return standardToArray(array); - } - } - - /** @see Maps#unmodifiableEntrySet(Set) */ -// static class UnmodifiableEntrySet -// extends UnmodifiableEntries implements Set> { -// UnmodifiableEntrySet(Set> entries) { -// super(entries); -// } -// -// // See java.util.Collections.UnmodifiableEntrySet for details on attacks. -// -// @Override public boolean equals(Object object) { -// return Sets.equalsImpl(this, object); -// } -// -// @Override public int hashCode() { -// return Sets.hashCodeImpl(this); -// } -// } - - /** - * Returns a {@link Converter} that converts values using {@link BiMap#get bimap.get()}, - * and whose inverse view converts values using - * {@link BiMap#inverse bimap.inverse()}{@code .get()}. - * - *

To use a plain {@link Map} as a {@link Function}, see - * {@link com.google.common.base.Functions#forMap(Map)} or - * {@link com.google.common.base.Functions#forMap(Map, Object)}. - * - * @since 16.0 - */ -// @Beta -// public static Converter asConverter(final BiMap bimap) { -// return new BiMapConverter(bimap); -// } -// -// private static final class BiMapConverter extends Converter implements Serializable { -// private final BiMap bimap; -// -// BiMapConverter(BiMap bimap) { -// this.bimap = checkNotNull(bimap); -// } -// -// @Override -// protected B doForward(A a) { -// return convert(bimap, a); -// } -// -// @Override -// protected A doBackward(B b) { -// return convert(bimap.inverse(), b); -// } -// -// private static Y convert(BiMap bimap, X input) { -// Y output = bimap.get(input); -// checkArgument(output != null, "No non-null mapping present for input: %s", input); -// return output; -// } -// -// @Override -// public boolean equals(Object object) { -// if (object instanceof BiMapConverter) { -// BiMapConverter that = (BiMapConverter) object; -// return this.bimap.equals(that.bimap); -// } -// return false; -// } -// -// @Override -// public int hashCode() { -// return bimap.hashCode(); -// } -// -// // There's really no good way to implement toString() without printing the entire BiMap, right? -// @Override -// public String toString() { -// return "Maps.asConverter(" + bimap + ")"; -// } -// -// private static final long serialVersionUID = 0L; -// } - - /** - * Returns a synchronized (thread-safe) bimap backed by the specified bimap. - * In order to guarantee serial access, it is critical that all access - * to the backing bimap is accomplished through the returned bimap. - * - *

It is imperative that the user manually synchronize on the returned map - * when accessing any of its collection views:

   {@code
-   *
-   *   BiMap map = Maps.synchronizedBiMap(
-   *       HashBiMap.create());
-   *   ...
-   *   Set set = map.keySet();  // Needn't be in synchronized block
-   *   ...
-   *   synchronized (map) {  // Synchronizing on map, not set!
-   *     Iterator it = set.iterator(); // Must be in synchronized block
-   *     while (it.hasNext()) {
-   *       foo(it.next());
-   *     }
-   *   }}
- * - *

Failure to follow this advice may result in non-deterministic behavior. - * - *

The returned bimap will be serializable if the specified bimap is - * serializable. - * - * @param bimap the bimap to be wrapped in a synchronized view - * @return a sychronized view of the specified bimap - */ -// public static BiMap synchronizedBiMap(BiMap bimap) { -// return Synchronized.biMap(bimap, null); -// } - - /** - * Returns an unmodifiable view of the specified bimap. This method allows - * modules to provide users with "read-only" access to internal bimaps. Query - * operations on the returned bimap "read through" to the specified bimap, and - * attempts to modify the returned map, whether direct or via its collection - * views, result in an {@code UnsupportedOperationException}. - * - *

The returned bimap will be serializable if the specified bimap is - * serializable. - * - * @param bimap the bimap for which an unmodifiable view is to be returned - * @return an unmodifiable view of the specified bimap - */ -// public static BiMap unmodifiableBiMap( -// BiMap bimap) { -// return new UnmodifiableBiMap(bimap, null); -// } -// -// /** @see Maps#unmodifiableBiMap(BiMap) */ -// private static class UnmodifiableBiMap -// extends ForwardingMap implements BiMap, Serializable { -// final Map unmodifiableMap; -// final BiMap delegate; -// BiMap inverse; -// transient Set values; -// -// UnmodifiableBiMap(BiMap delegate, -// BiMap inverse) { -// unmodifiableMap = Collections.unmodifiableMap(delegate); -// this.delegate = delegate; -// this.inverse = inverse; -// } -// -// @Override protected Map delegate() { -// return unmodifiableMap; -// } -// -// @Override -// public V forcePut(K key, V value) { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public BiMap inverse() { -// BiMap result = inverse; -// return (result == null) -// ? inverse = new UnmodifiableBiMap(delegate.inverse(), this) -// : result; -// } -// -// @Override public Set values() { -// Set result = values; -// return (result == null) -// ? values = Collections.unmodifiableSet(delegate.values()) -// : result; -// } -// -// private static final long serialVersionUID = 0; -// } - - /** - * Returns a view of a map where each value is transformed by a function. All - * other properties of the map, such as iteration order, are left intact. For - * example, the code:

   {@code
-   *
-   *   Map map = ImmutableMap.of("a", 4, "b", 9);
-   *   Function sqrt =
-   *       new Function() {
-   *         public Double apply(Integer in) {
-   *           return Math.sqrt((int) in);
-   *         }
-   *       };
-   *   Map transformed = Maps.transformValues(map, sqrt);
-   *   System.out.println(transformed);}
- * - * ... prints {@code {a=2.0, b=3.0}}. - * - *

Changes in the underlying map are reflected in this view. Conversely, - * this view supports removal operations, and these are reflected in the - * underlying map. - * - *

It's acceptable for the underlying map to contain null keys, and even - * null values provided that the function is capable of accepting null input. - * The transformed map might contain null values, if the function sometimes - * gives a null result. - * - *

The returned map is not thread-safe or serializable, even if the - * underlying map is. - * - *

The function is applied lazily, invoked when needed. This is necessary - * for the returned map to be a view, but it means that the function will be - * applied many times for bulk operations like {@link Map#containsValue} and - * {@code Map.toString()}. For this to perform well, {@code function} should - * be fast. To avoid lazy evaluation when the returned map doesn't need to be - * a view, copy the returned map into a new map of your choosing. - */ -// public static Map transformValues( -// Map fromMap, Function function) { -// return transformEntries(fromMap, asEntryTransformer(function)); -// } - - /** - * Returns a view of a sorted map where each value is transformed by a - * function. All other properties of the map, such as iteration order, are - * left intact. For example, the code:

   {@code
-   *
-   *   SortedMap map = ImmutableSortedMap.of("a", 4, "b", 9);
-   *   Function sqrt =
-   *       new Function() {
-   *         public Double apply(Integer in) {
-   *           return Math.sqrt((int) in);
-   *         }
-   *       };
-   *   SortedMap transformed =
-   *        Maps.transformValues(map, sqrt);
-   *   System.out.println(transformed);}
- * - * ... prints {@code {a=2.0, b=3.0}}. - * - *

Changes in the underlying map are reflected in this view. Conversely, - * this view supports removal operations, and these are reflected in the - * underlying map. - * - *

It's acceptable for the underlying map to contain null keys, and even - * null values provided that the function is capable of accepting null input. - * The transformed map might contain null values, if the function sometimes - * gives a null result. - * - *

The returned map is not thread-safe or serializable, even if the - * underlying map is. - * - *

The function is applied lazily, invoked when needed. This is necessary - * for the returned map to be a view, but it means that the function will be - * applied many times for bulk operations like {@link Map#containsValue} and - * {@code Map.toString()}. For this to perform well, {@code function} should - * be fast. To avoid lazy evaluation when the returned map doesn't need to be - * a view, copy the returned map into a new map of your choosing. - * - * @since 11.0 - */ -// public static SortedMap transformValues( -// SortedMap fromMap, Function function) { -// return transformEntries(fromMap, asEntryTransformer(function)); -// } - - /** - * Returns a view of a navigable map where each value is transformed by a - * function. All other properties of the map, such as iteration order, are - * left intact. For example, the code:

   {@code
-   *
-   *   NavigableMap map = Maps.newTreeMap();
-   *   map.put("a", 4);
-   *   map.put("b", 9);
-   *   Function sqrt =
-   *       new Function() {
-   *         public Double apply(Integer in) {
-   *           return Math.sqrt((int) in);
-   *         }
-   *       };
-   *   NavigableMap transformed =
-   *        Maps.transformNavigableValues(map, sqrt);
-   *   System.out.println(transformed);}
- * - * ... prints {@code {a=2.0, b=3.0}}. - * - * Changes in the underlying map are reflected in this view. - * Conversely, this view supports removal operations, and these are reflected - * in the underlying map. - * - *

It's acceptable for the underlying map to contain null keys, and even - * null values provided that the function is capable of accepting null input. - * The transformed map might contain null values, if the function sometimes - * gives a null result. - * - *

The returned map is not thread-safe or serializable, even if the - * underlying map is. - * - *

The function is applied lazily, invoked when needed. This is necessary - * for the returned map to be a view, but it means that the function will be - * applied many times for bulk operations like {@link Map#containsValue} and - * {@code Map.toString()}. For this to perform well, {@code function} should - * be fast. To avoid lazy evaluation when the returned map doesn't need to be - * a view, copy the returned map into a new map of your choosing. - * - * @since 13.0 - */ -// -// public static NavigableMap transformValues( -// NavigableMap fromMap, Function function) { -// return transformEntries(fromMap, asEntryTransformer(function)); -// } - - /** - * Returns a view of a map whose values are derived from the original map's - * entries. In contrast to {@link #transformValues}, this method's - * entry-transformation logic may depend on the key as well as the value. - * - *

All other properties of the transformed map, such as iteration order, - * are left intact. For example, the code:

   {@code
-   *
-   *   Map options =
-   *       ImmutableMap.of("verbose", true, "sort", false);
-   *   EntryTransformer flagPrefixer =
-   *       new EntryTransformer() {
-   *         public String transformEntry(String key, Boolean value) {
-   *           return value ? key : "no" + key;
-   *         }
-   *       };
-   *   Map transformed =
-   *       Maps.transformEntries(options, flagPrefixer);
-   *   System.out.println(transformed);}
- * - * ... prints {@code {verbose=verbose, sort=nosort}}. - * - *

Changes in the underlying map are reflected in this view. Conversely, - * this view supports removal operations, and these are reflected in the - * underlying map. - * - *

It's acceptable for the underlying map to contain null keys and null - * values provided that the transformer is capable of accepting null inputs. - * The transformed map might contain null values if the transformer sometimes - * gives a null result. - * - *

The returned map is not thread-safe or serializable, even if the - * underlying map is. - * - *

The transformer is applied lazily, invoked when needed. This is - * necessary for the returned map to be a view, but it means that the - * transformer will be applied many times for bulk operations like {@link - * Map#containsValue} and {@link Object#toString}. For this to perform well, - * {@code transformer} should be fast. To avoid lazy evaluation when the - * returned map doesn't need to be a view, copy the returned map into a new - * map of your choosing. - * - *

Warning: This method assumes that for any instance {@code k} of - * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies - * that {@code k2} is also of type {@code K}. Using an {@code - * EntryTransformer} key type for which this may not hold, such as {@code - * ArrayList}, may risk a {@code ClassCastException} when calling methods on - * the transformed map. - * - * @since 7.0 - */ -// public static Map transformEntries( -// Map fromMap, -// EntryTransformer transformer) { -// if (fromMap instanceof SortedMap) { -// return transformEntries((SortedMap) fromMap, transformer); -// } -// return new TransformedEntriesMap(fromMap, transformer); -// } - - /** - * Returns a view of a sorted map whose values are derived from the original - * sorted map's entries. In contrast to {@link #transformValues}, this - * method's entry-transformation logic may depend on the key as well as the - * value. - * - *

All other properties of the transformed map, such as iteration order, - * are left intact. For example, the code:

   {@code
-   *
-   *   Map options =
-   *       ImmutableSortedMap.of("verbose", true, "sort", false);
-   *   EntryTransformer flagPrefixer =
-   *       new EntryTransformer() {
-   *         public String transformEntry(String key, Boolean value) {
-   *           return value ? key : "yes" + key;
-   *         }
-   *       };
-   *   SortedMap transformed =
-   *       Maps.transformEntries(options, flagPrefixer);
-   *   System.out.println(transformed);}
- * - * ... prints {@code {sort=yessort, verbose=verbose}}. - * - *

Changes in the underlying map are reflected in this view. Conversely, - * this view supports removal operations, and these are reflected in the - * underlying map. - * - *

It's acceptable for the underlying map to contain null keys and null - * values provided that the transformer is capable of accepting null inputs. - * The transformed map might contain null values if the transformer sometimes - * gives a null result. - * - *

The returned map is not thread-safe or serializable, even if the - * underlying map is. - * - *

The transformer is applied lazily, invoked when needed. This is - * necessary for the returned map to be a view, but it means that the - * transformer will be applied many times for bulk operations like {@link - * Map#containsValue} and {@link Object#toString}. For this to perform well, - * {@code transformer} should be fast. To avoid lazy evaluation when the - * returned map doesn't need to be a view, copy the returned map into a new - * map of your choosing. - * - *

Warning: This method assumes that for any instance {@code k} of - * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies - * that {@code k2} is also of type {@code K}. Using an {@code - * EntryTransformer} key type for which this may not hold, such as {@code - * ArrayList}, may risk a {@code ClassCastException} when calling methods on - * the transformed map. - * - * @since 11.0 - */ -// public static SortedMap transformEntries( -// SortedMap fromMap, -// EntryTransformer transformer) { -// return Platform.mapsTransformEntriesSortedMap(fromMap, transformer); -// } - - /** - * Returns a view of a navigable map whose values are derived from the - * original navigable map's entries. In contrast to {@link - * #transformValues}, this method's entry-transformation logic may - * depend on the key as well as the value. - * - *

All other properties of the transformed map, such as iteration order, - * are left intact. For example, the code:

   {@code
-   *
-   *   NavigableMap options = Maps.newTreeMap();
-   *   options.put("verbose", false);
-   *   options.put("sort", true);
-   *   EntryTransformer flagPrefixer =
-   *       new EntryTransformer() {
-   *         public String transformEntry(String key, Boolean value) {
-   *           return value ? key : ("yes" + key);
-   *         }
-   *       };
-   *   NavigableMap transformed =
-   *       LabsMaps.transformNavigableEntries(options, flagPrefixer);
-   *   System.out.println(transformed);}
- * - * ... prints {@code {sort=yessort, verbose=verbose}}. - * - *

Changes in the underlying map are reflected in this view. - * Conversely, this view supports removal operations, and these are reflected - * in the underlying map. - * - *

It's acceptable for the underlying map to contain null keys and null - * values provided that the transformer is capable of accepting null inputs. - * The transformed map might contain null values if the transformer sometimes - * gives a null result. - * - *

The returned map is not thread-safe or serializable, even if the - * underlying map is. - * - *

The transformer is applied lazily, invoked when needed. This is - * necessary for the returned map to be a view, but it means that the - * transformer will be applied many times for bulk operations like {@link - * Map#containsValue} and {@link Object#toString}. For this to perform well, - * {@code transformer} should be fast. To avoid lazy evaluation when the - * returned map doesn't need to be a view, copy the returned map into a new - * map of your choosing. - * - *

Warning: This method assumes that for any instance {@code k} of - * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies - * that {@code k2} is also of type {@code K}. Using an {@code - * EntryTransformer} key type for which this may not hold, such as {@code - * ArrayList}, may risk a {@code ClassCastException} when calling methods on - * the transformed map. - * - * @since 13.0 - */ -// -// public static NavigableMap transformEntries( -// final NavigableMap fromMap, -// EntryTransformer transformer) { -// return new TransformedEntriesNavigableMap(fromMap, transformer); -// } -// -// static SortedMap transformEntriesIgnoreNavigable( -// SortedMap fromMap, -// EntryTransformer transformer) { -// return new TransformedEntriesSortedMap(fromMap, transformer); -// } - - /** - * A transformation of the value of a key-value pair, using both key and value - * as inputs. To apply the transformation to a map, use - * {@link Maps#transformEntries(Map, EntryTransformer)}. - * - * @param the key type of the input and output entries - * @param the value type of the input entry - * @param the value type of the output entry - * @since 7.0 - */ -// public interface EntryTransformer { -// /** -// * Determines an output value based on a key-value pair. This method is -// * generally expected, but not absolutely required, to have the -// * following properties: -// * -// *

    -// *
  • Its execution does not cause any observable side effects. -// *
  • The computation is consistent with equals; that is, -// * {@link Objects#equal Objects.equal}{@code (k1, k2) &&} -// * {@link Objects#equal}{@code (v1, v2)} implies that {@code -// * Objects.equal(transformer.transform(k1, v1), -// * transformer.transform(k2, v2))}. -// *
-// * -// * @throws NullPointerException if the key or value is null and this -// * transformer does not accept null arguments -// */ -// V2 transformEntry(K key, V1 value); -// } - - /** - * Views a function as an entry transformer that ignores the entry key. - */ -// static EntryTransformer -// asEntryTransformer(final Function function) { -// checkNotNull(function); -// return new EntryTransformer() { -// @Override -// public V2 transformEntry(K key, V1 value) { -// return function.apply(value); -// } -// }; -// } - -// static Function asValueToValueFunction( -// final EntryTransformer transformer, final K key) { -// checkNotNull(transformer); -// return new Function() { -// @Override -// public V2 apply(V1 v1) { -// return transformer.transformEntry(key, v1); -// } -// }; -// } - -// /** -// * Views an entry transformer as a function from {@code Entry} to values. -// */ -// static Function, V2> asEntryToValueFunction( -// final EntryTransformer transformer) { -// checkNotNull(transformer); -// return new Function, V2>() { -// @Override -// public V2 apply(Entry entry) { -// return transformer.transformEntry(entry.getKey(), entry.getValue()); -// } -// }; -// } - -// /** -// * Returns a view of an entry transformed by the specified transformer. -// */ -// static Entry transformEntry( -// final EntryTransformer transformer, final Entry entry) { -// checkNotNull(transformer); -// checkNotNull(entry); -// return new AbstractMapEntry() { -// @Override -// public K getKey() { -// return entry.getKey(); -// } -// -// @Override -// public V2 getValue() { -// return transformer.transformEntry(entry.getKey(), entry.getValue()); -// } -// }; -// } - -// /** -// * Views an entry transformer as a function from entries to entries. -// */ -// static Function, Entry> asEntryToEntryFunction( -// final EntryTransformer transformer) { -// checkNotNull(transformer); -// return new Function, Entry>() { -// @Override -// public Entry apply(final Entry entry) { -// return transformEntry(transformer, entry); -// } -// }; -// } - -// static class TransformedEntriesMap -// extends ImprovedAbstractMap { -// final Map fromMap; -// final EntryTransformer transformer; -// -// TransformedEntriesMap( -// Map fromMap, -// EntryTransformer transformer) { -// this.fromMap = checkNotNull(fromMap); -// this.transformer = checkNotNull(transformer); -// } -// -// @Override public int size() { -// return fromMap.size(); -// } -// -// @Override public boolean containsKey(Object key) { -// return fromMap.containsKey(key); -// } -// -// // safe as long as the user followed the Warning in the javadoc -// -// @Override public V2 get(Object key) { -// V1 value = fromMap.get(key); -// return (value != null || fromMap.containsKey(key)) -// ? transformer.transformEntry((K) key, value) -// : null; -// } -// -// // safe as long as the user followed the Warning in the javadoc -// -// @Override public V2 remove(Object key) { -// return fromMap.containsKey(key) -// ? transformer.transformEntry((K) key, fromMap.remove(key)) -// : null; -// } -// -// @Override public void clear() { -// fromMap.clear(); -// } -// -// @Override public Set keySet() { -// return fromMap.keySet(); -// } -// -// @Override -// protected Set> createEntrySet() { -// return new EntrySet() { -// @Override Map map() { -// return TransformedEntriesMap.this; -// } -// -// @Override public Iterator> iterator() { -// return Iterators.transform(fromMap.entrySet().iterator(), -// Maps.asEntryToEntryFunction(transformer)); -// } -// }; -// } -// } - -// static class TransformedEntriesSortedMap -// extends TransformedEntriesMap implements SortedMap { -// -// protected SortedMap fromMap() { -// return (SortedMap) fromMap; -// } -// -// TransformedEntriesSortedMap(SortedMap fromMap, -// EntryTransformer transformer) { -// super(fromMap, transformer); -// } -// -// @Override public Comparator comparator() { -// return fromMap().comparator(); -// } -// -// @Override public K firstKey() { -// return fromMap().firstKey(); -// } -// -// @Override public SortedMap headMap(K toKey) { -// return transformEntries(fromMap().headMap(toKey), transformer); -// } -// -// @Override public K lastKey() { -// return fromMap().lastKey(); -// } -// -// @Override public SortedMap subMap(K fromKey, K toKey) { -// return transformEntries( -// fromMap().subMap(fromKey, toKey), transformer); -// } -// -// @Override public SortedMap tailMap(K fromKey) { -// return transformEntries(fromMap().tailMap(fromKey), transformer); -// } -// } -// -// -// private static class TransformedEntriesNavigableMap -// extends TransformedEntriesSortedMap -// implements NavigableMap { -// -// TransformedEntriesNavigableMap(NavigableMap fromMap, -// EntryTransformer transformer) { -// super(fromMap, transformer); -// } -// -// @Override public Entry ceilingEntry(K key) { -// return transformEntry(fromMap().ceilingEntry(key)); -// } -// -// @Override public K ceilingKey(K key) { -// return fromMap().ceilingKey(key); -// } -// -// @Override public NavigableSet descendingKeySet() { -// return fromMap().descendingKeySet(); -// } -// -// @Override public NavigableMap descendingMap() { -// return transformEntries(fromMap().descendingMap(), transformer); -// } -// -// @Override public Entry firstEntry() { -// return transformEntry(fromMap().firstEntry()); -// } -// @Override public Entry floorEntry(K key) { -// return transformEntry(fromMap().floorEntry(key)); -// } -// -// @Override public K floorKey(K key) { -// return fromMap().floorKey(key); -// } -// -// @Override public NavigableMap headMap(K toKey) { -// return headMap(toKey, false); -// } -// -// @Override public NavigableMap headMap(K toKey, boolean inclusive) { -// return transformEntries( -// fromMap().headMap(toKey, inclusive), transformer); -// } -// -// @Override public Entry higherEntry(K key) { -// return transformEntry(fromMap().higherEntry(key)); -// } -// -// @Override public K higherKey(K key) { -// return fromMap().higherKey(key); -// } -// -// @Override public Entry lastEntry() { -// return transformEntry(fromMap().lastEntry()); -// } -// -// @Override public Entry lowerEntry(K key) { -// return transformEntry(fromMap().lowerEntry(key)); -// } -// -// @Override public K lowerKey(K key) { -// return fromMap().lowerKey(key); -// } -// -// @Override public NavigableSet navigableKeySet() { -// return fromMap().navigableKeySet(); -// } -// -// @Override public Entry pollFirstEntry() { -// return transformEntry(fromMap().pollFirstEntry()); -// } -// -// @Override public Entry pollLastEntry() { -// return transformEntry(fromMap().pollLastEntry()); -// } -// -// @Override public NavigableMap subMap( -// K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { -// return transformEntries( -// fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive), -// transformer); -// } -// -// @Override public NavigableMap subMap(K fromKey, K toKey) { -// return subMap(fromKey, true, toKey, false); -// } -// -// @Override public NavigableMap tailMap(K fromKey) { -// return tailMap(fromKey, true); -// } -// -// @Override public NavigableMap tailMap(K fromKey, boolean inclusive) { -// return transformEntries( -// fromMap().tailMap(fromKey, inclusive), transformer); -// } -// -// -// private Entry transformEntry(Entry entry) { -// return (entry == null) ? null : Maps.transformEntry(transformer, entry); -// } -// -// @Override protected NavigableMap fromMap() { -// return (NavigableMap) super.fromMap(); -// } -// } - - static Predicate> keyPredicateOnEntries(Predicate keyPredicate) { - return compose(keyPredicate, Maps.keyFunction()); - } - - static Predicate> valuePredicateOnEntries(Predicate valuePredicate) { - return compose(valuePredicate, Maps.valueFunction()); - } - - /** - * Returns a map containing the mappings in {@code unfiltered} whose keys - * satisfy a predicate. The returned map is a live view of {@code unfiltered}; - * changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a key that - * doesn't satisfy the predicate, the map's {@code put()} and {@code putAll()} - * methods throw an {@link IllegalArgumentException}. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings whose keys satisfy the - * filter will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code keyPredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. Do not provide a - * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is - * inconsistent with equals. - */ -// public static Map filterKeys( -// Map unfiltered, final Predicate keyPredicate) { -// if (unfiltered instanceof SortedMap) { -// return filterKeys((SortedMap) unfiltered, keyPredicate); -// } else if (unfiltered instanceof BiMap) { -// return filterKeys((BiMap) unfiltered, keyPredicate); -// } -// checkNotNull(keyPredicate); -// Predicate> entryPredicate = keyPredicateOnEntries(keyPredicate); -// return (unfiltered instanceof AbstractFilteredMap) -// ? filterFiltered((AbstractFilteredMap) unfiltered, entryPredicate) -// : new FilteredKeyMap( -// checkNotNull(unfiltered), keyPredicate, entryPredicate); -// } - - /** - * Returns a sorted map containing the mappings in {@code unfiltered} whose - * keys satisfy a predicate. The returned map is a live view of {@code - * unfiltered}; changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a key that - * doesn't satisfy the predicate, the map's {@code put()} and {@code putAll()} - * methods throw an {@link IllegalArgumentException}. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings whose keys satisfy the - * filter will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code keyPredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. Do not provide a - * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is - * inconsistent with equals. - * - * @since 11.0 - */ -// public static SortedMap filterKeys( -// SortedMap unfiltered, final Predicate keyPredicate) { -// // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better -// // performance. -// return filterEntries(unfiltered, Maps.keyPredicateOnEntries(keyPredicate)); -// } - - /** - * Returns a navigable map containing the mappings in {@code unfiltered} whose - * keys satisfy a predicate. The returned map is a live view of {@code - * unfiltered}; changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a key that - * doesn't satisfy the predicate, the map's {@code put()} and {@code putAll()} - * methods throw an {@link IllegalArgumentException}. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings whose keys satisfy the - * filter will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code keyPredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. Do not provide a - * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is - * inconsistent with equals. - * - * @since 14.0 - */ -// -// public static NavigableMap filterKeys( -// NavigableMap unfiltered, final Predicate keyPredicate) { -// // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better -// // performance. -// return filterEntries(unfiltered, Maps.keyPredicateOnEntries(keyPredicate)); -// } - - /** - * Returns a bimap containing the mappings in {@code unfiltered} whose keys satisfy a predicate. - * The returned bimap is a live view of {@code unfiltered}; changes to one affect the other. - * - *

The resulting bimap's {@code keySet()}, {@code entrySet()}, and {@code values()} views have - * iterators that don't support {@code remove()}, but all other methods are supported by the - * bimap and its views. When given a key that doesn't satisfy the predicate, the bimap's {@code - * put()}, {@code forcePut()} and {@code putAll()} methods throw an {@link - * IllegalArgumentException}. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called on the filtered - * bimap or its views, only mappings that satisfy the filter will be removed from the underlying - * bimap. - * - *

The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is. - * - *

Many of the filtered bimap's methods, such as {@code size()}, iterate across every key in - * the underlying bimap and determine which satisfy the filter. When a live view is not - * needed, it may be faster to copy the filtered bimap and use the copy. - * - *

Warning: {@code entryPredicate} must be consistent with equals , as - * documented at {@link Predicate#apply}. - * - * @since 14.0 - */ -// public static BiMap filterKeys( -// BiMap unfiltered, final Predicate keyPredicate) { -// checkNotNull(keyPredicate); -// return filterEntries(unfiltered, Maps.keyPredicateOnEntries(keyPredicate)); -// } - - /** - * Returns a map containing the mappings in {@code unfiltered} whose values - * satisfy a predicate. The returned map is a live view of {@code unfiltered}; - * changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a value - * that doesn't satisfy the predicate, the map's {@code put()}, {@code - * putAll()}, and {@link Entry#setValue} methods throw an {@link - * IllegalArgumentException}. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings whose values satisfy the - * filter will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code valuePredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. Do not provide a - * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is - * inconsistent with equals. - */ -// public static Map filterValues( -// Map unfiltered, final Predicate valuePredicate) { -// if (unfiltered instanceof SortedMap) { -// return filterValues((SortedMap) unfiltered, valuePredicate); -// } else if (unfiltered instanceof BiMap) { -// return filterValues((BiMap) unfiltered, valuePredicate); -// } -// return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); -// } - - /** - * Returns a sorted map containing the mappings in {@code unfiltered} whose - * values satisfy a predicate. The returned map is a live view of {@code - * unfiltered}; changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a value - * that doesn't satisfy the predicate, the map's {@code put()}, {@code - * putAll()}, and {@link Entry#setValue} methods throw an {@link - * IllegalArgumentException}. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings whose values satisfy the - * filter will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code valuePredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. Do not provide a - * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is - * inconsistent with equals. - * - * @since 11.0 - */ -// public static SortedMap filterValues( -// SortedMap unfiltered, final Predicate valuePredicate) { -// return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); -// } - - /** - * Returns a navigable map containing the mappings in {@code unfiltered} whose - * values satisfy a predicate. The returned map is a live view of {@code - * unfiltered}; changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a value - * that doesn't satisfy the predicate, the map's {@code put()}, {@code - * putAll()}, and {@link Entry#setValue} methods throw an {@link - * IllegalArgumentException}. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings whose values satisfy the - * filter will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code valuePredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. Do not provide a - * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is - * inconsistent with equals. - * - * @since 14.0 - */ -// -// public static NavigableMap filterValues( -// NavigableMap unfiltered, final Predicate valuePredicate) { -// return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); -// } - - /** - * Returns a bimap containing the mappings in {@code unfiltered} whose values satisfy a - * predicate. The returned bimap is a live view of {@code unfiltered}; changes to one affect the - * other. - * - *

The resulting bimap's {@code keySet()}, {@code entrySet()}, and {@code values()} views have - * iterators that don't support {@code remove()}, but all other methods are supported by the - * bimap and its views. When given a value that doesn't satisfy the predicate, the bimap's - * {@code put()}, {@code forcePut()} and {@code putAll()} methods throw an {@link - * IllegalArgumentException}. Similarly, the map's entries have a {@link Entry#setValue} method - * that throws an {@link IllegalArgumentException} when the provided value doesn't satisfy the - * predicate. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called on the filtered - * bimap or its views, only mappings that satisfy the filter will be removed from the underlying - * bimap. - * - *

The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is. - * - *

Many of the filtered bimap's methods, such as {@code size()}, iterate across every value in - * the underlying bimap and determine which satisfy the filter. When a live view is not - * needed, it may be faster to copy the filtered bimap and use the copy. - * - *

Warning: {@code entryPredicate} must be consistent with equals , as - * documented at {@link Predicate#apply}. - * - * @since 14.0 - */ -// public static BiMap filterValues( -// BiMap unfiltered, final Predicate valuePredicate) { -// return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); -// } - - /** - * Returns a map containing the mappings in {@code unfiltered} that satisfy a - * predicate. The returned map is a live view of {@code unfiltered}; changes - * to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a - * key/value pair that doesn't satisfy the predicate, the map's {@code put()} - * and {@code putAll()} methods throw an {@link IllegalArgumentException}. - * Similarly, the map's entries have a {@link Entry#setValue} method that - * throws an {@link IllegalArgumentException} when the existing key and the - * provided value don't satisfy the predicate. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings that satisfy the filter - * will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code entryPredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. - */ -// public static Map filterEntries( -// Map unfiltered, Predicate> entryPredicate) { -// if (unfiltered instanceof SortedMap) { -// return filterEntries((SortedMap) unfiltered, entryPredicate); -// } else if (unfiltered instanceof BiMap) { -// return filterEntries((BiMap) unfiltered, entryPredicate); -// } -// checkNotNull(entryPredicate); -// return (unfiltered instanceof AbstractFilteredMap) -// ? filterFiltered((AbstractFilteredMap) unfiltered, entryPredicate) -// : new FilteredEntryMap(checkNotNull(unfiltered), entryPredicate); -// } - - /** - * Returns a sorted map containing the mappings in {@code unfiltered} that - * satisfy a predicate. The returned map is a live view of {@code unfiltered}; - * changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a - * key/value pair that doesn't satisfy the predicate, the map's {@code put()} - * and {@code putAll()} methods throw an {@link IllegalArgumentException}. - * Similarly, the map's entries have a {@link Entry#setValue} method that - * throws an {@link IllegalArgumentException} when the existing key and the - * provided value don't satisfy the predicate. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings that satisfy the filter - * will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code entryPredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. - * - * @since 11.0 - */ -// public static SortedMap filterEntries( -// SortedMap unfiltered, -// Predicate> entryPredicate) { -// return Platform.mapsFilterSortedMap(unfiltered, entryPredicate); -// } - -// static SortedMap filterSortedIgnoreNavigable( -// SortedMap unfiltered, -// Predicate> entryPredicate) { -// checkNotNull(entryPredicate); -// return (unfiltered instanceof FilteredEntrySortedMap) -// ? filterFiltered((FilteredEntrySortedMap) unfiltered, entryPredicate) -// : new FilteredEntrySortedMap(checkNotNull(unfiltered), entryPredicate); -// } - - /** - * Returns a sorted map containing the mappings in {@code unfiltered} that - * satisfy a predicate. The returned map is a live view of {@code unfiltered}; - * changes to one affect the other. - * - *

The resulting map's {@code keySet()}, {@code entrySet()}, and {@code - * values()} views have iterators that don't support {@code remove()}, but all - * other methods are supported by the map and its views. When given a - * key/value pair that doesn't satisfy the predicate, the map's {@code put()} - * and {@code putAll()} methods throw an {@link IllegalArgumentException}. - * Similarly, the map's entries have a {@link Entry#setValue} method that - * throws an {@link IllegalArgumentException} when the existing key and the - * provided value don't satisfy the predicate. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called - * on the filtered map or its views, only mappings that satisfy the filter - * will be removed from the underlying map. - * - *

The returned map isn't threadsafe or serializable, even if {@code - * unfiltered} is. - * - *

Many of the filtered map's methods, such as {@code size()}, - * iterate across every key/value mapping in the underlying map and determine - * which satisfy the filter. When a live view is not needed, it may be - * faster to copy the filtered map and use the copy. - * - *

Warning: {@code entryPredicate} must be consistent with - * equals, as documented at {@link Predicate#apply}. - * - * @since 14.0 - */ -// -// public static NavigableMap filterEntries( -// NavigableMap unfiltered, -// Predicate> entryPredicate) { -// checkNotNull(entryPredicate); -// return (unfiltered instanceof FilteredEntryNavigableMap) -// ? filterFiltered((FilteredEntryNavigableMap) unfiltered, entryPredicate) -// : new FilteredEntryNavigableMap(checkNotNull(unfiltered), entryPredicate); -// } - - /** - * Returns a bimap containing the mappings in {@code unfiltered} that satisfy a predicate. The - * returned bimap is a live view of {@code unfiltered}; changes to one affect the other. - * - *

The resulting bimap's {@code keySet()}, {@code entrySet()}, and {@code values()} views have - * iterators that don't support {@code remove()}, but all other methods are supported by the bimap - * and its views. When given a key/value pair that doesn't satisfy the predicate, the bimap's - * {@code put()}, {@code forcePut()} and {@code putAll()} methods throw an - * {@link IllegalArgumentException}. Similarly, the map's entries have an {@link Entry#setValue} - * method that throws an {@link IllegalArgumentException} when the existing key and the provided - * value don't satisfy the predicate. - * - *

When methods such as {@code removeAll()} and {@code clear()} are called on the filtered - * bimap or its views, only mappings that satisfy the filter will be removed from the underlying - * bimap. - * - *

The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is. - * - *

Many of the filtered bimap's methods, such as {@code size()}, iterate across every - * key/value mapping in the underlying bimap and determine which satisfy the filter. When a live - * view is not needed, it may be faster to copy the filtered bimap and use the copy. - * - *

Warning: {@code entryPredicate} must be consistent with equals , as - * documented at {@link Predicate#apply}. - * - * @since 14.0 - */ -// public static BiMap filterEntries( -// BiMap unfiltered, Predicate> entryPredicate) { -// checkNotNull(unfiltered); -// checkNotNull(entryPredicate); -// return (unfiltered instanceof FilteredEntryBiMap) -// ? filterFiltered((FilteredEntryBiMap) unfiltered, entryPredicate) -// : new FilteredEntryBiMap(unfiltered, entryPredicate); -// } -// -// /** -// * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when -// * filtering a filtered map. -// */ -// private static Map filterFiltered(AbstractFilteredMap map, -// Predicate> entryPredicate) { -// return new FilteredEntryMap(map.unfiltered, -// Predicates.>and(map.predicate, entryPredicate)); -// } - -// private abstract static class AbstractFilteredMap -// extends ImprovedAbstractMap { -// final Map unfiltered; -// final Predicate> predicate; -// -// AbstractFilteredMap( -// Map unfiltered, Predicate> predicate) { -// this.unfiltered = unfiltered; -// this.predicate = predicate; -// } -// -// boolean apply(Object key, V value) { -// // This method is called only when the key is in the map, implying that -// // key is a K. -// -// K k = (K) key; -// return predicate.apply(Maps.immutableEntry(k, value)); -// } -// -// @Override public V put(K key, V value) { -// checkArgument(apply(key, value)); -// return unfiltered.put(key, value); -// } -// -// @Override public void putAll(Map map) { -// for (Entry entry : map.entrySet()) { -// checkArgument(apply(entry.getKey(), entry.getValue())); -// } -// unfiltered.putAll(map); -// } -// -// @Override public boolean containsKey(Object key) { -// return unfiltered.containsKey(key) && apply(key, unfiltered.get(key)); -// } -// -// @Override public V get(Object key) { -// V value = unfiltered.get(key); -// return ((value != null) && apply(key, value)) ? value : null; -// } -// -// @Override public boolean isEmpty() { -// return entrySet().isEmpty(); -// } -// -// @Override public V remove(Object key) { -// return containsKey(key) ? unfiltered.remove(key) : null; -// } -// -// @Override -// Collection createValues() { -// return new FilteredMapValues(this, unfiltered, predicate); -// } -// } -// -// private static final class FilteredMapValues extends Maps.Values { -// Map unfiltered; -// Predicate> predicate; -// -// FilteredMapValues(Map filteredMap, Map unfiltered, -// Predicate> predicate) { -// super(filteredMap); -// this.unfiltered = unfiltered; -// this.predicate = predicate; -// } -// -// @Override public boolean remove(Object o) { -// return Iterables.removeFirstMatching(unfiltered.entrySet(), -// Predicates.>and(predicate, Maps.valuePredicateOnEntries(equalTo(o)))) -// != null; -// } -// -// private boolean removeIf(Predicate valuePredicate) { -// return Iterables.removeIf(unfiltered.entrySet(), Predicates.>and( -// predicate, Maps.valuePredicateOnEntries(valuePredicate))); -// } -// -// @Override public boolean removeAll(Collection collection) { -// return removeIf(in(collection)); -// } -// -// @Override public boolean retainAll(Collection collection) { -// return removeIf(not(in(collection))); -// } -// -// @Override public Object[] toArray() { -// // creating an ArrayList so filtering happens once -// return Lists.newArrayList(iterator()).toArray(); -// } -// -// @Override public T[] toArray(T[] array) { -// return Lists.newArrayList(iterator()).toArray(array); -// } -// } -// -// private static class FilteredKeyMap extends AbstractFilteredMap { -// Predicate keyPredicate; -// -// FilteredKeyMap(Map unfiltered, Predicate keyPredicate, -// Predicate> entryPredicate) { -// super(unfiltered, entryPredicate); -// this.keyPredicate = keyPredicate; -// } -// -// @Override -// protected Set> createEntrySet() { -// return Sets.filter(unfiltered.entrySet(), predicate); -// } -// -// @Override -// Set createKeySet() { -// return Sets.filter(unfiltered.keySet(), keyPredicate); -// } -// -// // The cast is called only when the key is in the unfiltered map, implying -// // that key is a K. -// @Override -// -// public boolean containsKey(Object key) { -// return unfiltered.containsKey(key) && keyPredicate.apply((K) key); -// } -// } -// -// static class FilteredEntryMap extends AbstractFilteredMap { -// /** -// * Entries in this set satisfy the predicate, but they don't validate the -// * input to {@code Entry.setValue()}. -// */ -// final Set> filteredEntrySet; -// -// FilteredEntryMap( -// Map unfiltered, Predicate> entryPredicate) { -// super(unfiltered, entryPredicate); -// filteredEntrySet = Sets.filter(unfiltered.entrySet(), predicate); -// } -// -// @Override -// protected Set> createEntrySet() { -// return new EntrySet(); -// } -// -// private class EntrySet extends ForwardingSet> { -// @Override protected Set> delegate() { -// return filteredEntrySet; -// } -// -// @Override public Iterator> iterator() { -// return new TransformedIterator, Entry>(filteredEntrySet.iterator()) { -// @Override -// Entry transform(final Entry entry) { -// return new ForwardingMapEntry() { -// @Override -// protected Entry delegate() { -// return entry; -// } -// -// @Override -// public V setValue(V newValue) { -// checkArgument(apply(getKey(), newValue)); -// return super.setValue(newValue); -// } -// }; -// } -// }; -// } -// } -// -// @Override -// Set createKeySet() { -// return new KeySet(); -// } -// -// class KeySet extends Maps.KeySet { -// KeySet() { -// super(FilteredEntryMap.this); -// } -// -// @Override public boolean remove(Object o) { -// if (containsKey(o)) { -// unfiltered.remove(o); -// return true; -// } -// return false; -// } -// -// private boolean removeIf(Predicate keyPredicate) { -// return Iterables.removeIf(unfiltered.entrySet(), Predicates.>and( -// predicate, Maps.keyPredicateOnEntries(keyPredicate))); -// } -// -// @Override -// public boolean removeAll(Collection c) { -// return removeIf(in(c)); -// } -// -// @Override -// public boolean retainAll(Collection c) { -// return removeIf(not(in(c))); -// } -// -// @Override public Object[] toArray() { -// // creating an ArrayList so filtering happens once -// return Lists.newArrayList(iterator()).toArray(); -// } -// -// @Override public T[] toArray(T[] array) { -// return Lists.newArrayList(iterator()).toArray(array); -// } -// } -// } - - /** - * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when - * filtering a filtered sorted map. - */ -// private static SortedMap filterFiltered( -// FilteredEntrySortedMap map, -// Predicate> entryPredicate) { -// Predicate> predicate -// = Predicates.and(map.predicate, entryPredicate); -// return new FilteredEntrySortedMap(map.sortedMap(), predicate); -// } -// -// private static class FilteredEntrySortedMap -// extends FilteredEntryMap implements SortedMap { -// -// FilteredEntrySortedMap(SortedMap unfiltered, -// Predicate> entryPredicate) { -// super(unfiltered, entryPredicate); -// } -// -// SortedMap sortedMap() { -// return (SortedMap) unfiltered; -// } -// -// @Override public SortedSet keySet() { -// return (SortedSet) super.keySet(); -// } -// -// @Override -// SortedSet createKeySet() { -// return new SortedKeySet(); -// } -// -// class SortedKeySet extends KeySet implements SortedSet { -// @Override -// public Comparator comparator() { -// return sortedMap().comparator(); -// } -// -// @Override -// public SortedSet subSet(K fromElement, K toElement) { -// return (SortedSet) subMap(fromElement, toElement).keySet(); -// } -// -// @Override -// public SortedSet headSet(K toElement) { -// return (SortedSet) headMap(toElement).keySet(); -// } -// -// @Override -// public SortedSet tailSet(K fromElement) { -// return (SortedSet) tailMap(fromElement).keySet(); -// } -// -// @Override -// public K first() { -// return firstKey(); -// } -// -// @Override -// public K last() { -// return lastKey(); -// } -// } -// -// @Override public Comparator comparator() { -// return sortedMap().comparator(); -// } -// -// @Override public K firstKey() { -// // correctly throws NoSuchElementException when filtered map is empty. -// return keySet().iterator().next(); -// } -// -// @Override public K lastKey() { -// SortedMap headMap = sortedMap(); -// while (true) { -// // correctly throws NoSuchElementException when filtered map is empty. -// K key = headMap.lastKey(); -// if (apply(key, unfiltered.get(key))) { -// return key; -// } -// headMap = sortedMap().headMap(key); -// } -// } -// -// @Override public SortedMap headMap(K toKey) { -// return new FilteredEntrySortedMap(sortedMap().headMap(toKey), predicate); -// } -// -// @Override public SortedMap subMap(K fromKey, K toKey) { -// return new FilteredEntrySortedMap( -// sortedMap().subMap(fromKey, toKey), predicate); -// } -// -// @Override public SortedMap tailMap(K fromKey) { -// return new FilteredEntrySortedMap( -// sortedMap().tailMap(fromKey), predicate); -// } -// } - - /** - * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when - * filtering a filtered navigable map. - */ -// -// private static NavigableMap filterFiltered( -// FilteredEntryNavigableMap map, -// Predicate> entryPredicate) { -// Predicate> predicate -// = Predicates.and(map.entryPredicate, entryPredicate); -// return new FilteredEntryNavigableMap(map.unfiltered, predicate); -// } -// -// -// private static class FilteredEntryNavigableMap extends AbstractNavigableMap { -// /* -// * It's less code to extend AbstractNavigableMap and forward the filtering logic to -// * FilteredEntryMap than to extend FilteredEntrySortedMap and reimplement all the NavigableMap -// * methods. -// */ -// -// private final NavigableMap unfiltered; -// private final Predicate> entryPredicate; -// private final Map filteredDelegate; -// -// FilteredEntryNavigableMap( -// NavigableMap unfiltered, Predicate> entryPredicate) { -// this.unfiltered = checkNotNull(unfiltered); -// this.entryPredicate = entryPredicate; -// this.filteredDelegate = new FilteredEntryMap(unfiltered, entryPredicate); -// } -// -// @Override -// public Comparator comparator() { -// return unfiltered.comparator(); -// } -// -// @Override -// public NavigableSet navigableKeySet() { -// return new Maps.NavigableKeySet(this) { -// @Override -// public boolean removeAll(Collection c) { -// return Iterators.removeIf(unfiltered.entrySet().iterator(), -// Predicates.>and(entryPredicate, Maps.keyPredicateOnEntries(in(c)))); -// } -// -// @Override -// public boolean retainAll(Collection c) { -// return Iterators.removeIf(unfiltered.entrySet().iterator(), Predicates.>and( -// entryPredicate, Maps.keyPredicateOnEntries(not(in(c))))); -// } -// }; -// } -// -// @Override -// public Collection values() { -// return new FilteredMapValues(this, unfiltered, entryPredicate); -// } -// -// @Override -// Iterator> entryIterator() { -// return Iterators.filter(unfiltered.entrySet().iterator(), entryPredicate); -// } -// -// @Override -// Iterator> descendingEntryIterator() { -// return Iterators.filter(unfiltered.descendingMap().entrySet().iterator(), entryPredicate); -// } -// -// @Override -// public int size() { -// return filteredDelegate.size(); -// } -// -// @Override -// -// public V get(Object key) { -// return filteredDelegate.get(key); -// } -// -// @Override -// public boolean containsKey(Object key) { -// return filteredDelegate.containsKey(key); -// } -// -// @Override -// public V put(K key, V value) { -// return filteredDelegate.put(key, value); -// } -// -// @Override -// public V remove(Object key) { -// return filteredDelegate.remove(key); -// } -// -// @Override -// public void putAll(Map m) { -// filteredDelegate.putAll(m); -// } -// -// @Override -// public void clear() { -// filteredDelegate.clear(); -// } -// -// @Override -// public Set> entrySet() { -// return filteredDelegate.entrySet(); -// } -// -// @Override -// public Entry pollFirstEntry() { -// return Iterables.removeFirstMatching(unfiltered.entrySet(), entryPredicate); -// } -// -// @Override -// public Entry pollLastEntry() { -// return Iterables.removeFirstMatching(unfiltered.descendingMap().entrySet(), entryPredicate); -// } -// -// @Override -// public NavigableMap descendingMap() { -// return filterEntries(unfiltered.descendingMap(), entryPredicate); -// } -// -// @Override -// public NavigableMap subMap( -// K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { -// return filterEntries( -// unfiltered.subMap(fromKey, fromInclusive, toKey, toInclusive), entryPredicate); -// } -// -// @Override -// public NavigableMap headMap(K toKey, boolean inclusive) { -// return filterEntries(unfiltered.headMap(toKey, inclusive), entryPredicate); -// } -// -// @Override -// public NavigableMap tailMap(K fromKey, boolean inclusive) { -// return filterEntries(unfiltered.tailMap(fromKey, inclusive), entryPredicate); -// } -// } - - /** - * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when - * filtering a filtered map. - */ -// private static BiMap filterFiltered( -// FilteredEntryBiMap map, Predicate> entryPredicate) { -// Predicate> predicate = Predicates.and(map.predicate, entryPredicate); -// return new FilteredEntryBiMap(map.unfiltered(), predicate); -// } -// -// static final class FilteredEntryBiMap extends FilteredEntryMap -// implements BiMap { -// private final BiMap inverse; -// -// private static Predicate> inversePredicate( -// final Predicate> forwardPredicate) { -// return new Predicate>() { -// @Override -// public boolean apply(Entry input) { -// return forwardPredicate.apply( -// Maps.immutableEntry(input.getValue(), input.getKey())); -// } -// }; -// } -// -// FilteredEntryBiMap(BiMap delegate, -// Predicate> predicate) { -// super(delegate, predicate); -// this.inverse = new FilteredEntryBiMap( -// delegate.inverse(), inversePredicate(predicate), this); -// } -// -// private FilteredEntryBiMap( -// BiMap delegate, Predicate> predicate, -// BiMap inverse) { -// super(delegate, predicate); -// this.inverse = inverse; -// } -// -// BiMap unfiltered() { -// return (BiMap) unfiltered; -// } -// -// @Override -// public V forcePut(K key, V value) { -// checkArgument(apply(key, value)); -// return unfiltered().forcePut(key, value); -// } -// -// @Override -// public BiMap inverse() { -// return inverse; -// } -// -// @Override -// public Set values() { -// return inverse.keySet(); -// } -// } - - /** - * Returns an unmodifiable view of the specified navigable map. Query operations on the returned - * map read through to the specified map, and attempts to modify the returned map, whether direct - * or via its views, result in an {@code UnsupportedOperationException}. - * - *

The returned navigable map will be serializable if the specified navigable map is - * serializable. - * - * @param map the navigable map for which an unmodifiable view is to be returned - * @return an unmodifiable view of the specified navigable map - * @since 12.0 - */ -// -// public static NavigableMap unmodifiableNavigableMap(NavigableMap map) { -// checkNotNull(map); -// if (map instanceof UnmodifiableNavigableMap) { -// return map; -// } else { -// return new UnmodifiableNavigableMap(map); -// } -// } -// -// private static Entry unmodifiableOrNull(Entry entry) { -// return (entry == null) ? null : Maps.unmodifiableEntry(entry); -// } -// -// -// static class UnmodifiableNavigableMap -// extends ForwardingSortedMap implements NavigableMap, Serializable { -// private final NavigableMap delegate; -// -// UnmodifiableNavigableMap(NavigableMap delegate) { -// this.delegate = delegate; -// } -// -// UnmodifiableNavigableMap( -// NavigableMap delegate, UnmodifiableNavigableMap descendingMap) { -// this.delegate = delegate; -// this.descendingMap = descendingMap; -// } -// -// @Override -// protected SortedMap delegate() { -// return Collections.unmodifiableSortedMap(delegate); -// } -// -// @Override -// public Entry lowerEntry(K key) { -// return unmodifiableOrNull(delegate.lowerEntry(key)); -// } -// -// @Override -// public K lowerKey(K key) { -// return delegate.lowerKey(key); -// } -// -// @Override -// public Entry floorEntry(K key) { -// return unmodifiableOrNull(delegate.floorEntry(key)); -// } -// -// @Override -// public K floorKey(K key) { -// return delegate.floorKey(key); -// } -// -// @Override -// public Entry ceilingEntry(K key) { -// return unmodifiableOrNull(delegate.ceilingEntry(key)); -// } -// -// @Override -// public K ceilingKey(K key) { -// return delegate.ceilingKey(key); -// } -// -// @Override -// public Entry higherEntry(K key) { -// return unmodifiableOrNull(delegate.higherEntry(key)); -// } -// -// @Override -// public K higherKey(K key) { -// return delegate.higherKey(key); -// } -// -// @Override -// public Entry firstEntry() { -// return unmodifiableOrNull(delegate.firstEntry()); -// } -// -// @Override -// public Entry lastEntry() { -// return unmodifiableOrNull(delegate.lastEntry()); -// } -// -// @Override -// public final Entry pollFirstEntry() { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public final Entry pollLastEntry() { -// throw new UnsupportedOperationException(); -// } -// -// private transient UnmodifiableNavigableMap descendingMap; -// -// @Override -// public NavigableMap descendingMap() { -// UnmodifiableNavigableMap result = descendingMap; -// return (result == null) -// ? descendingMap = new UnmodifiableNavigableMap(delegate.descendingMap(), this) -// : result; -// } -// -// @Override -// public Set keySet() { -// return navigableKeySet(); -// } -// -// @Override -// public NavigableSet navigableKeySet() { -// return Sets.unmodifiableNavigableSet(delegate.navigableKeySet()); -// } -// -// @Override -// public NavigableSet descendingKeySet() { -// return Sets.unmodifiableNavigableSet(delegate.descendingKeySet()); -// } -// -// @Override -// public SortedMap subMap(K fromKey, K toKey) { -// return subMap(fromKey, true, toKey, false); -// } -// -// @Override -// public SortedMap headMap(K toKey) { -// return headMap(toKey, false); -// } -// -// @Override -// public SortedMap tailMap(K fromKey) { -// return tailMap(fromKey, true); -// } -// -// @Override -// public -// NavigableMap -// subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { -// return Maps.unmodifiableNavigableMap(delegate.subMap( -// fromKey, -// fromInclusive, -// toKey, -// toInclusive)); -// } -// -// @Override -// public NavigableMap headMap(K toKey, boolean inclusive) { -// return Maps.unmodifiableNavigableMap(delegate.headMap(toKey, inclusive)); -// } -// -// @Override -// public NavigableMap tailMap(K fromKey, boolean inclusive) { -// return Maps.unmodifiableNavigableMap(delegate.tailMap(fromKey, inclusive)); -// } -// } - - /** - * Returns a synchronized (thread-safe) navigable map backed by the specified - * navigable map. In order to guarantee serial access, it is critical that - * all access to the backing navigable map is accomplished - * through the returned navigable map (or its views). - * - *

It is imperative that the user manually synchronize on the returned - * navigable map when iterating over any of its collection views, or the - * collections views of any of its {@code descendingMap}, {@code subMap}, - * {@code headMap} or {@code tailMap} views.

   {@code
-   *
-   *   NavigableMap map = synchronizedNavigableMap(new TreeMap());
-   *
-   *   // Needn't be in synchronized block
-   *   NavigableSet set = map.navigableKeySet();
-   *
-   *   synchronized (map) { // Synchronizing on map, not set!
-   *     Iterator it = set.iterator(); // Must be in synchronized block
-   *     while (it.hasNext()) {
-   *       foo(it.next());
-   *     }
-   *   }}
- * - *

or:

   {@code
-   *
-   *   NavigableMap map = synchronizedNavigableMap(new TreeMap());
-   *   NavigableMap map2 = map.subMap(foo, false, bar, true);
-   *
-   *   // Needn't be in synchronized block
-   *   NavigableSet set2 = map2.descendingKeySet();
-   *
-   *   synchronized (map) { // Synchronizing on map, not map2 or set2!
-   *     Iterator it = set2.iterator(); // Must be in synchronized block
-   *     while (it.hasNext()) {
-   *       foo(it.next());
-   *     }
-   *   }}
- * - *

Failure to follow this advice may result in non-deterministic behavior. - * - *

The returned navigable map will be serializable if the specified - * navigable map is serializable. - * - * @param navigableMap the navigable map to be "wrapped" in a synchronized - * navigable map. - * @return a synchronized view of the specified navigable map. - * @since 13.0 - */ -// -// public static NavigableMap synchronizedNavigableMap( -// NavigableMap navigableMap) { -// return Synchronized.navigableMap(navigableMap); -// } - - /** - * {@code AbstractMap} extension that implements {@link #isEmpty()} as {@code - * entrySet().isEmpty()} instead of {@code size() == 0} to speed up - * implementations where {@code size()} is O(n), and it delegates the {@code - * isEmpty()} methods of its key set and value collection to this - * implementation. - */ - - abstract static class ImprovedAbstractMap extends AbstractMap { - /** - * Creates the entry set to be returned by {@link #entrySet()}. This method - * is invoked at most once on a given map, at the time when {@code entrySet} - * is first called. - */ - abstract Set> createEntrySet(); - - private transient Set> entrySet; - - @Override public Set> entrySet() { - Set> result = entrySet; - return (result == null) ? entrySet = createEntrySet() : result; - } - - private transient Set keySet; - - @Override public Set keySet() { - Set result = keySet; - return (result == null) ? keySet = createKeySet() : result; - } - - Set createKeySet() { - return new KeySet(this); - } - - private transient Collection values; - - @Override public Collection values() { - Collection result = values; - return (result == null) ? values = createValues() : result; - } - - Collection createValues() { - return new Values(this); - } - } - - /** - * Delegates to {@link Map#get}. Returns {@code null} on {@code - * ClassCastException} and {@code NullPointerException}. - */ - static V safeGet(Map map, Object key) { - checkNotNull(map); - try { - return map.get(key); - } catch (ClassCastException e) { - return null; - } catch (NullPointerException e) { - return null; - } - } - - /** - * Delegates to {@link Map#containsKey}. Returns {@code false} on {@code - * ClassCastException} and {@code NullPointerException}. - */ - static boolean safeContainsKey(Map map, Object key) { - checkNotNull(map); - try { - return map.containsKey(key); - } catch (ClassCastException e) { - return false; - } catch (NullPointerException e) { - return false; - } - } - - /** - * Delegates to {@link Map#remove}. Returns {@code null} on {@code - * ClassCastException} and {@code NullPointerException}. - */ - static V safeRemove(Map map, Object key) { - checkNotNull(map); - try { - return map.remove(key); - } catch (ClassCastException e) { - return null; - } catch (NullPointerException e) { - return null; - } - } - - /** - * An admittedly inefficient implementation of {@link Map#containsKey}. - */ -// static boolean containsKeyImpl(Map map, Object key) { -// return Iterators.contains(keyIterator(map.entrySet().iterator()), key); -// } - - /** - * An implementation of {@link Map#containsValue}. - */ -// static boolean containsValueImpl(Map map, Object value) { -// return Iterators.contains(valueIterator(map.entrySet().iterator()), value); -// } - - /** - * Implements {@code Collection.contains} safely for forwarding collections of - * map entries. If {@code o} is an instance of {@code Map.Entry}, it is - * wrapped using {@link #unmodifiableEntry} to protect against a possible - * nefarious equals method. - * - *

Note that {@code c} is the backing (delegate) collection, rather than - * the forwarding collection. - * - * @param c the delegate (unwrapped) collection of map entries - * @param o the object that might be contained in {@code c} - * @return {@code true} if {@code c} contains {@code o} - */ - static boolean containsEntryImpl(Collection> c, Object o) { - if (!(o instanceof Entry)) { - return false; - } - return c.contains(unmodifiableEntry((Entry) o)); - } - - /** - * Implements {@code Collection.remove} safely for forwarding collections of - * map entries. If {@code o} is an instance of {@code Map.Entry}, it is - * wrapped using {@link #unmodifiableEntry} to protect against a possible - * nefarious equals method. - * - *

Note that {@code c} is backing (delegate) collection, rather than the - * forwarding collection. - * - * @param c the delegate (unwrapped) collection of map entries - * @param o the object to remove from {@code c} - * @return {@code true} if {@code c} was changed - */ -// static boolean removeEntryImpl(Collection> c, Object o) { -// if (!(o instanceof Entry)) { -// return false; -// } -// return c.remove(unmodifiableEntry((Entry) o)); -// } - - /** - * An implementation of {@link Map#equals}. - */ - static boolean equalsImpl(Map map, Object object) { - if (map == object) { - return true; - } else if (object instanceof Map) { - Map o = (Map) object; - return map.entrySet().equals(o.entrySet()); - } - return false; - } - -// static final MapJoiner STANDARD_JOINER = -// Collections2.STANDARD_JOINER.withKeyValueSeparator("="); -// -// /** -// * An implementation of {@link Map#toString}. -// */ -// static String toStringImpl(Map map) { -// StringBuilder sb -// = Collections2.newStringBuilderForCollection(map.size()).append('{'); -// STANDARD_JOINER.appendTo(sb, map); -// return sb.append('}').toString(); -// } - - /** - * An implementation of {@link Map#putAll}. - */ -// static void putAllImpl( -// Map self, Map map) { -// for (Map.Entry entry : map.entrySet()) { -// self.put(entry.getKey(), entry.getValue()); -// } -// } - - static class KeySet extends Sets.ImprovedAbstractSet { - final Map map; - - KeySet(Map map) { - this.map = checkNotNull(map); - } - - Map map() { - return map; - } - - @Override public Iterator iterator() { - return keyIterator(map().entrySet().iterator()); - } - - @Override public int size() { - return map().size(); - } - - @Override public boolean isEmpty() { - return map().isEmpty(); - } - - @Override public boolean contains(Object o) { - return map().containsKey(o); - } - - @Override public boolean remove(Object o) { - if (contains(o)) { - map().remove(o); - return true; - } - return false; - } - - @Override public void clear() { - map().clear(); - } - } - -// -// static K keyOrNull(Entry entry) { -// return (entry == null) ? null : entry.getKey(); -// } -// -// -// static V valueOrNull(Entry entry) { -// return (entry == null) ? null : entry.getValue(); -// } - -// static class SortedKeySet extends KeySet implements SortedSet { -// SortedKeySet(SortedMap map) { -// super(map); -// } -// -// @Override -// SortedMap map() { -// return (SortedMap) super.map(); -// } -// -// @Override -// public Comparator comparator() { -// return map().comparator(); -// } -// -// @Override -// public SortedSet subSet(K fromElement, K toElement) { -// return new SortedKeySet(map().subMap(fromElement, toElement)); -// } -// -// @Override -// public SortedSet headSet(K toElement) { -// return new SortedKeySet(map().headMap(toElement)); -// } -// -// @Override -// public SortedSet tailSet(K fromElement) { -// return new SortedKeySet(map().tailMap(fromElement)); -// } -// -// @Override -// public K first() { -// return map().firstKey(); -// } -// -// @Override -// public K last() { -// return map().lastKey(); -// } -// } - -// -// static class NavigableKeySet extends SortedKeySet implements NavigableSet { -// NavigableKeySet(NavigableMap map) { -// super(map); -// } -// -// @Override -// NavigableMap map() { -// return (NavigableMap) map; -// } -// -// @Override -// public K lower(K e) { -// return map().lowerKey(e); -// } -// -// @Override -// public K floor(K e) { -// return map().floorKey(e); -// } -// -// @Override -// public K ceiling(K e) { -// return map().ceilingKey(e); -// } -// -// @Override -// public K higher(K e) { -// return map().higherKey(e); -// } -// -// @Override -// public K pollFirst() { -// return keyOrNull(map().pollFirstEntry()); -// } -// -// @Override -// public K pollLast() { -// return keyOrNull(map().pollLastEntry()); -// } -// -// @Override -// public NavigableSet descendingSet() { -// return map().descendingKeySet(); -// } -// -// @Override -// public Iterator descendingIterator() { -// return descendingSet().iterator(); -// } -// -// @Override -// public NavigableSet subSet( -// K fromElement, -// boolean fromInclusive, -// K toElement, -// boolean toInclusive) { -// return map().subMap(fromElement, fromInclusive, toElement, toInclusive).navigableKeySet(); -// } -// -// @Override -// public NavigableSet headSet(K toElement, boolean inclusive) { -// return map().headMap(toElement, inclusive).navigableKeySet(); -// } -// -// @Override -// public NavigableSet tailSet(K fromElement, boolean inclusive) { -// return map().tailMap(fromElement, inclusive).navigableKeySet(); -// } -// -// @Override -// public SortedSet subSet(K fromElement, K toElement) { -// return subSet(fromElement, true, toElement, false); -// } -// -// @Override -// public SortedSet headSet(K toElement) { -// return headSet(toElement, false); -// } -// -// @Override -// public SortedSet tailSet(K fromElement) { -// return tailSet(fromElement, true); -// } -// } - - static class Values extends AbstractCollection { - final Map map; - - Values(Map map) { - this.map = checkNotNull(map); - } - - final Map map() { - return map; - } - - @Override public Iterator iterator() { - return valueIterator(map().entrySet().iterator()); - } - - @Override public boolean remove(Object o) { - try { - return super.remove(o); - } catch (UnsupportedOperationException e) { - for (Entry entry : map().entrySet()) { - if (Preconditions.equal(o, entry.getValue())) { - map().remove(entry.getKey()); - return true; - } - } - return false; - } - } - - @Override public boolean removeAll(Collection c) { - try { - return super.removeAll(checkNotNull(c)); - } catch (UnsupportedOperationException e) { - Set toRemove = Sets.newHashSet(); - for (Entry entry : map().entrySet()) { - if (c.contains(entry.getValue())) { - toRemove.add(entry.getKey()); - } - } - return map().keySet().removeAll(toRemove); - } - } - - @Override public boolean retainAll(Collection c) { - try { - return super.retainAll(checkNotNull(c)); - } catch (UnsupportedOperationException e) { - Set toRetain = Sets.newHashSet(); - for (Entry entry : map().entrySet()) { - if (c.contains(entry.getValue())) { - toRetain.add(entry.getKey()); - } - } - return map().keySet().retainAll(toRetain); - } - } - - @Override public int size() { - return map().size(); - } - - @Override public boolean isEmpty() { - return map().isEmpty(); - } - - @Override public boolean contains(Object o) { - return map().containsValue(o); - } - - @Override public void clear() { - map().clear(); - } - } - - abstract static class EntrySet - extends Sets.ImprovedAbstractSet> { - abstract Map map(); - - @Override public int size() { - return map().size(); - } - - @Override public void clear() { - map().clear(); - } - - @Override public boolean contains(Object o) { - if (o instanceof Entry) { - Entry entry = (Entry) o; - Object key = entry.getKey(); - V value = Maps.safeGet(map(), key); - return Preconditions.equal(value, entry.getValue()) - && (value != null || map().containsKey(key)); - } - return false; - } - - @Override public boolean isEmpty() { - return map().isEmpty(); - } - - @Override public boolean remove(Object o) { - if (contains(o)) { - Entry entry = (Entry) o; - return map().keySet().remove(entry.getKey()); - } - return false; - } - - @Override public boolean removeAll(Collection c) { - try { - return super.removeAll(checkNotNull(c)); - } catch (UnsupportedOperationException e) { - // if the iterators don't support remove - return Sets.removeAllImpl(this, c.iterator()); - } - } - - @Override public boolean retainAll(Collection c) { - try { - return super.retainAll(checkNotNull(c)); - } catch (UnsupportedOperationException e) { - // if the iterators don't support remove - Set keys = Sets.newHashSetWithExpectedSize(c.size()); - for (Object o : c) { - if (contains(o)) { - Entry entry = (Entry) o; - keys.add(entry.getKey()); - } - } - return map().keySet().retainAll(keys); - } - } - } - -// -// abstract static class DescendingMap extends ForwardingMap -// implements NavigableMap { -// -// abstract NavigableMap forward(); -// -// @Override -// protected final Map delegate() { -// return forward(); -// } -// -// private transient Comparator comparator; -// -// -// @Override -// public Comparator comparator() { -// Comparator result = comparator; -// if (result == null) { -// Comparator forwardCmp = forward().comparator(); -// if (forwardCmp == null) { -// forwardCmp = (Comparator) Ordering.natural(); -// } -// result = comparator = reverse(forwardCmp); -// } -// return result; -// } -// -// // If we inline this, we get a javac error. -// private static Ordering reverse(Comparator forward) { -// return Ordering.from(forward).reverse(); -// } -// -// @Override -// public K firstKey() { -// return forward().lastKey(); -// } -// -// @Override -// public K lastKey() { -// return forward().firstKey(); -// } -// -// @Override -// public Entry lowerEntry(K key) { -// return forward().higherEntry(key); -// } -// -// @Override -// public K lowerKey(K key) { -// return forward().higherKey(key); -// } -// -// @Override -// public Entry floorEntry(K key) { -// return forward().ceilingEntry(key); -// } -// -// @Override -// public K floorKey(K key) { -// return forward().ceilingKey(key); -// } -// -// @Override -// public Entry ceilingEntry(K key) { -// return forward().floorEntry(key); -// } -// -// @Override -// public K ceilingKey(K key) { -// return forward().floorKey(key); -// } -// -// @Override -// public Entry higherEntry(K key) { -// return forward().lowerEntry(key); -// } -// -// @Override -// public K higherKey(K key) { -// return forward().lowerKey(key); -// } -// -// @Override -// public Entry firstEntry() { -// return forward().lastEntry(); -// } -// -// @Override -// public Entry lastEntry() { -// return forward().firstEntry(); -// } -// -// @Override -// public Entry pollFirstEntry() { -// return forward().pollLastEntry(); -// } -// -// @Override -// public Entry pollLastEntry() { -// return forward().pollFirstEntry(); -// } -// -// @Override -// public NavigableMap descendingMap() { -// return forward(); -// } -// -// private transient Set> entrySet; -// -// @Override -// public Set> entrySet() { -// Set> result = entrySet; -// return (result == null) ? entrySet = createEntrySet() : result; -// } -// -// abstract Iterator> entryIterator(); -// -// Set> createEntrySet() { -// return new EntrySet() { -// @Override -// Map map() { -// return DescendingMap.this; -// } -// -// @Override -// public Iterator> iterator() { -// return entryIterator(); -// } -// }; -// } -// -// @Override -// public Set keySet() { -// return navigableKeySet(); -// } -// -// private transient NavigableSet navigableKeySet; -// -// @Override -// public NavigableSet navigableKeySet() { -// NavigableSet result = navigableKeySet; -// return (result == null) ? navigableKeySet = new NavigableKeySet(this) : result; -// } -// -// @Override -// public NavigableSet descendingKeySet() { -// return forward().navigableKeySet(); -// } -// -// @Override -// public -// NavigableMap -// subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { -// return forward().subMap(toKey, toInclusive, fromKey, fromInclusive).descendingMap(); -// } -// -// @Override -// public NavigableMap headMap(K toKey, boolean inclusive) { -// return forward().tailMap(toKey, inclusive).descendingMap(); -// } -// -// @Override -// public NavigableMap tailMap(K fromKey, boolean inclusive) { -// return forward().headMap(fromKey, inclusive).descendingMap(); -// } -// -// @Override -// public SortedMap subMap(K fromKey, K toKey) { -// return subMap(fromKey, true, toKey, false); -// } -// -// @Override -// public SortedMap headMap(K toKey) { -// return headMap(toKey, false); -// } -// -// @Override -// public SortedMap tailMap(K fromKey) { -// return tailMap(fromKey, true); -// } -// -// @Override -// public Collection values() { -// return new Values(this); -// } -// -// @Override -// public String toString() { -// return standardToString(); -// } -// } -} diff --git a/java/src/game/collect/ObjectArrays.java b/java/src/game/collect/ObjectArrays.java deleted file mode 100644 index 2087cbe..0000000 --- a/java/src/game/collect/ObjectArrays.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.lang.reflect.Array; -import java.util.Collection; - -/** - * Static utility methods pertaining to object arrays. - * - * @author Kevin Bourrillion - * @since 2.0 (imported from Google Collections Library) - */ - -final class ObjectArrays { - static final Object[] EMPTY_ARRAY = new Object[0]; - - private ObjectArrays() {} - - /** - * Returns a new array of the given length with the specified component type. - * - * @param type the component type - * @param length the length of the new array - */ -// -// -// public static T[] newArray(Class type, int length) { -// return (T[]) Array.newInstance(type, length); -// } - - /** - * Returns a new array of the given length with the same type as a reference - * array. - * - * @param reference any array of the desired type - * @param length the length of the new array - */ - public static T[] newArray(T[] reference, int length) { -// return Platform.newArray(reference, length); - Class type = reference.getClass().getComponentType(); - - // the cast is safe because - // result.getClass() == reference.getClass().getComponentType() - - T[] result = (T[]) Array.newInstance(type, length); - return result; - } - - /** - * Returns a new array that contains the concatenated contents of two arrays. - * - * @param first the first array of elements to concatenate - * @param second the second array of elements to concatenate - * @param type the component type of the returned array - */ -// -// public static T[] concat(T[] first, T[] second, Class type) { -// T[] result = newArray(type, first.length + second.length); -// System.arraycopy(first, 0, result, 0, first.length); -// System.arraycopy(second, 0, result, first.length, second.length); -// return result; -// } - - /** - * Returns a new array that prepends {@code element} to {@code array}. - * - * @param element the element to prepend to the front of {@code array} - * @param array the array of elements to append - * @return an array whose size is one larger than {@code array}, with - * {@code element} occupying the first position, and the - * elements of {@code array} occupying the remaining elements. - */ -// public static T[] concat(T element, T[] array) { -// T[] result = newArray(array, array.length + 1); -// result[0] = element; -// System.arraycopy(array, 0, result, 1, array.length); -// return result; -// } - - /** - * Returns a new array that appends {@code element} to {@code array}. - * - * @param array the array of elements to prepend - * @param element the element to append to the end - * @return an array whose size is one larger than {@code array}, with - * the same contents as {@code array}, plus {@code element} occupying the - * last position. - */ -// public static T[] concat(T[] array, T element) { -// T[] result = arraysCopyOf(array, array.length + 1); -// result[array.length] = element; -// return result; -// } - - /** GWT safe version of Arrays.copyOf. */ - static T[] arraysCopyOf(T[] original, int newLength) { - T[] copy = newArray(original, newLength); - System.arraycopy( - original, 0, copy, 0, Math.min(original.length, newLength)); - return copy; - } - - /** - * Returns an array containing all of the elements in the specified - * collection; the runtime type of the returned array is that of the specified - * array. If the collection fits in the specified array, it is returned - * therein. Otherwise, a new array is allocated with the runtime type of the - * specified array and the size of the specified collection. - * - *

If the collection fits in the specified array with room to spare (i.e., - * the array has more elements than the collection), the element in the array - * immediately following the end of the collection is set to {@code null}. - * This is useful in determining the length of the collection only if - * the caller knows that the collection does not contain any null elements. - * - *

This method returns the elements in the order they are returned by the - * collection's iterator. - * - *

TODO(kevinb): support concurrently modified collections? - * - * @param c the collection for which to return an array of elements - * @param array the array in which to place the collection elements - * @throws ArrayStoreException if the runtime type of the specified array is - * not a supertype of the runtime type of every element in the specified - * collection - */ - static T[] toArrayImpl(Collection c, T[] array) { - int size = c.size(); - if (array.length < size) { - array = newArray(array, size); - } - fillArray(c, array); - if (array.length > size) { - array[size] = null; - } - return array; - } - - /** - * Implementation of {@link Collection#toArray(Object[])} for collections backed by an object - * array. the runtime type of the returned array is that of the specified array. If the collection - * fits in the specified array, it is returned therein. Otherwise, a new array is allocated with - * the runtime type of the specified array and the size of the specified collection. - * - *

If the collection fits in the specified array with room to spare (i.e., the array has more - * elements than the collection), the element in the array immediately following the end of the - * collection is set to {@code null}. This is useful in determining the length of the collection - * only if the caller knows that the collection does not contain any null elements. - */ -// static T[] toArrayImpl(Object[] src, int offset, int len, T[] dst) { -// checkPositionIndexes(offset, offset + len, src.length); -// if (dst.length < len) { -// dst = newArray(dst, len); -// } else if (dst.length > len) { -// dst[len] = null; -// } -// System.arraycopy(src, offset, dst, 0, len); -// return dst; -// } - - /** - * Returns an array containing all of the elements in the specified - * collection. This method returns the elements in the order they are returned - * by the collection's iterator. The returned array is "safe" in that no - * references to it are maintained by the collection. The caller is thus free - * to modify the returned array. - * - *

This method assumes that the collection size doesn't change while the - * method is running. - * - *

TODO(kevinb): support concurrently modified collections? - * - * @param c the collection for which to return an array of elements - */ -// static Object[] toArrayImpl(Collection c) { -// return fillArray(c, new Object[c.size()]); -// } - - /** - * Returns a copy of the specified subrange of the specified array that is literally an Object[], - * and not e.g. a {@code String[]}. - */ -// static Object[] copyAsObjectArray(Object[] elements, int offset, int length) { -// checkPositionIndexes(offset, offset + length, elements.length); -// if (length == 0) { -// return EMPTY_ARRAY; -// } -// Object[] result = new Object[length]; -// System.arraycopy(elements, offset, result, 0, length); -// return result; -// } - - private static Object[] fillArray(Iterable elements, Object[] array) { - int i = 0; - for (Object element : elements) { - array[i++] = element; - } - return array; - } - - /** - * Swaps {@code array[i]} with {@code array[j]}. - */ -// static void swap(Object[] array, int i, int j) { -// Object temp = array[i]; -// array[i] = array[j]; -// array[j] = temp; -// } - - static Object[] checkElementsNotNull(Object... array) { - return checkElementsNotNull(array, array.length); - } - - static Object[] checkElementsNotNull(Object[] array, int length) { - for (int i = 0; i < length; i++) { - checkElementNotNull(array[i], i); - } - return array; - } - - // We do this instead of Preconditions.checkNotNull to save boxing and array - // creation cost. - static Object checkElementNotNull(Object element, int index) { - if (element == null) { - throw new NullPointerException("at index " + index); - } - return element; - } -} diff --git a/java/src/game/collect/Preconditions.java b/java/src/game/collect/Preconditions.java deleted file mode 100644 index 18dbe7e..0000000 --- a/java/src/game/collect/Preconditions.java +++ /dev/null @@ -1,350 +0,0 @@ -package game.collect; - -final class Preconditions { - private Preconditions() {} - - /** - * Ensures the truth of an expression involving one or more parameters to the calling method. - * - * @param expression a boolean expression - * @throws IllegalArgumentException if {@code expression} is false - */ - public static void checkArgument(boolean expression) { - if (!expression) { - throw new IllegalArgumentException(); - } - } - - /** - * Ensures the truth of an expression involving one or more parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessage the exception message to use if the check fails; will be converted to a - * string using {@link String#valueOf(Object)} - * @throws IllegalArgumentException if {@code expression} is false - */ - public static void checkArgument(boolean expression, Object errorMessage) { - if (!expression) { - throw new IllegalArgumentException(String.valueOf(errorMessage)); - } - } - - /** - * Ensures the truth of an expression involving one or more parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessageTemplate a template for the exception message should the check fail. The - * message is formed by replacing each {@code %s} placeholder in the template with an - * argument. These are matched by position - the first {@code %s} gets {@code - * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message - * in square braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message template. Arguments - * are converted to strings using {@link String#valueOf(Object)}. - * @throws IllegalArgumentException if {@code expression} is false - * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or - * {@code errorMessageArgs} is null (don't let this happen) - */ - public static void checkArgument(boolean expression, - String errorMessageTemplate, - Object... errorMessageArgs) { - if (!expression) { - throw new IllegalArgumentException(String.format(errorMessageTemplate, errorMessageArgs)); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling instance, but not - * involving any parameters to the calling method. - * - * @param expression a boolean expression - * @throws IllegalStateException if {@code expression} is false - */ - public static void checkState(boolean expression) { - if (!expression) { - throw new IllegalStateException(); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling instance, but not - * involving any parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessage the exception message to use if the check fails; will be converted to a - * string using {@link String#valueOf(Object)} - * @throws IllegalStateException if {@code expression} is false - */ - public static void checkState(boolean expression, Object errorMessage) { - if (!expression) { - throw new IllegalStateException(String.valueOf(errorMessage)); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling instance, but not - * involving any parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessageTemplate a template for the exception message should the check fail. The - * message is formed by replacing each {@code %s} placeholder in the template with an - * argument. These are matched by position - the first {@code %s} gets {@code - * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message - * in square braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message template. Arguments - * are converted to strings using {@link String#valueOf(Object)}. - * @throws IllegalStateException if {@code expression} is false - * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or - * {@code errorMessageArgs} is null (don't let this happen) - */ -// public static void checkState(boolean expression, -// String errorMessageTemplate, -// Object... errorMessageArgs) { -// if (!expression) { -// throw new IllegalStateException(String.format(errorMessageTemplate, errorMessageArgs)); -// } -// } - - /** - * Ensures that an object reference passed as a parameter to the calling method is not null. - * - * @param reference an object reference - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference) { - if (reference == null) { - throw new NullPointerException(); - } - return reference; - } - - /** - * Ensures that an object reference passed as a parameter to the calling method is not null. - * - * @param reference an object reference - * @param errorMessage the exception message to use if the check fails; will be converted to a - * string using {@link String#valueOf(Object)} - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference, Object errorMessage) { - if (reference == null) { - throw new NullPointerException(String.valueOf(errorMessage)); - } - return reference; - } - - /** - * Ensures that an object reference passed as a parameter to the calling method is not null. - * - * @param reference an object reference - * @param errorMessageTemplate a template for the exception message should the check fail. The - * message is formed by replacing each {@code %s} placeholder in the template with an - * argument. These are matched by position - the first {@code %s} gets {@code - * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message - * in square braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message template. Arguments - * are converted to strings using {@link String#valueOf(Object)}. - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ -// public static T checkNotNull(T reference, -// String errorMessageTemplate, -// Object... errorMessageArgs) { -// if (reference == null) { -// // If either of these parameters is null, the right thing happens anyway -// throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); -// } -// return reference; -// } - - /* - * All recent hotspots (as of 2009) *really* like to have the natural code - * - * if (guardExpression) { - * throw new BadException(messageExpression); - * } - * - * refactored so that messageExpression is moved to a separate String-returning method. - * - * if (guardExpression) { - * throw new BadException(badMsg(...)); - * } - * - * The alternative natural refactorings into void or Exception-returning methods are much slower. - * This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This - * is a hotspot optimizer bug, which should be fixed, but that's a separate, big project). - * - * The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a - * RangeCheckMicroBenchmark in the JDK that was used to test this. - * - * But the methods in this class want to throw different exceptions, depending on the args, so it - * appears that this pattern is not directly applicable. But we can use the ridiculous, devious - * trick of throwing an exception in the middle of the construction of another exception. Hotspot - * is fine with that. - */ - - /** - * Ensures that {@code index} specifies a valid element in an array, list or string of size - * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. - * - * @param index a user-supplied index identifying an element of an array, list or string - * @param size the size of that array, list or string - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ -// public static int checkElementIndex(int index, int size) { -// return checkElementIndex(index, size, "index"); -// } - - /** - * Ensures that {@code index} specifies a valid element in an array, list or string of size - * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. - * - * @param index a user-supplied index identifying an element of an array, list or string - * @param size the size of that array, list or string - * @param desc the text to use to describe this index in an error message - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkElementIndex( - int index, int size) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException(badElementIndex(index, size)); - } - return index; - } - - private static String badElementIndex(int index, int size) { - if (index < 0) { - return String.format("index (%d) must not be negative", index); - } else if (size < 0) { - throw new IllegalArgumentException("negative size: " + size); - } else { // index >= size - return String.format("index (%d) must be less than size (%d)", index, size); - } - } - - /** - * Ensures that {@code index} specifies a valid position in an array, list or string of - * size {@code size}. A position index may range from zero to {@code size}, inclusive. - * - * @param index a user-supplied index identifying a position in an array, list or string - * @param size the size of that array, list or string - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ -// public static int checkPositionIndex(int index, int size) { -// return checkPositionIndex(index, size, "index"); -// } - - /** - * Ensures that {@code index} specifies a valid position in an array, list or string of - * size {@code size}. A position index may range from zero to {@code size}, inclusive. - * - * @param index a user-supplied index identifying a position in an array, list or string - * @param size the size of that array, list or string - * @param desc the text to use to describe this index in an error message - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkPositionIndex(int index, int size) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (index < 0 || index > size) { - throw new IndexOutOfBoundsException(badPositionIndex(index, size, "index")); - } - return index; - } - - private static String badPositionIndex(int index, int size, String desc) { - if (index < 0) { - return String.format("%s (%d) must not be negative", desc, index); - } else if (size < 0) { - throw new IllegalArgumentException("negative size: " + size); - } else { // index > size - return String.format("%s (%d) must not be greater than size (%s)", desc, index, size); - } - } - - /** - * Ensures that {@code start} and {@code end} specify a valid positions in an array, list - * or string of size {@code size}, and are in order. A position index may range from zero to - * {@code size}, inclusive. - * - * @param start a user-supplied index identifying a starting position in an array, list or string - * @param end a user-supplied index identifying a ending position in an array, list or string - * @param size the size of that array, list or string - * @throws IndexOutOfBoundsException if either index is negative or is greater than {@code size}, - * or if {@code end} is less than {@code start} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static void checkPositionIndexes(int start, int end, int size) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (start < 0 || end < start || end > size) { - throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); - } - } - - private static String badPositionIndexes(int start, int end, int size) { - if (start < 0 || start > size) { - return badPositionIndex(start, size, "start index"); - } - if (end < 0 || end > size) { - return badPositionIndex(end, size, "end index"); - } - // end < start - return String.format("end index (%d) must not be less than start index (%d)", end, start); - } - -public static boolean equal(Object a, Object b) { - return a == b || (a != null && a.equals(b)); - } - - /** - * Substitutes each {@code %s} in {@code template} with an argument. These are matched by - * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than - * placeholders, the unmatched arguments will be appended to the end of the formatted message in - * square braces. - * - * @param template a non-null string containing 0 or more {@code %s} placeholders. - * @param args the arguments to be substituted into the message template. Arguments are converted - * to strings using {@link String#valueOf(Object)}. Arguments can be null. - */ -// // Note that this is somewhat-improperly used from Verify.java as well. -// static String format(String template, Object... args) { -// template = String.valueOf(template); // null -> "null" -// -// // start substituting the arguments into the '%s' placeholders -// StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); -// int templateStart = 0; -// int i = 0; -// while (i < args.length) { -// int placeholderStart = template.indexOf("%s", templateStart); -// if (placeholderStart == -1) { -// break; -// } -// builder.append(template.substring(templateStart, placeholderStart)); -// builder.append(args[i++]); -// templateStart = placeholderStart + 2; -// } -// builder.append(template.substring(templateStart)); -// -// // if we run out of placeholders, append the extra args in square braces -// if (i < args.length) { -// builder.append(" ["); -// builder.append(args[i++]); -// while (i < args.length) { -// builder.append(", "); -// builder.append(args[i++]); -// } -// builder.append(']'); -// } -// -// return builder.toString(); -// } -} diff --git a/java/src/game/collect/RegularImmutableAsList.java b/java/src/game/collect/RegularImmutableAsList.java deleted file mode 100644 index a5d724d..0000000 --- a/java/src/game/collect/RegularImmutableAsList.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -/** - * An {@link ImmutableAsList} implementation specialized for when the delegate collection is - * already backed by an {@code ImmutableList} or array. - * - * @author Louis Wasserman - */ - - // uses writeReplace, not default serialization -class RegularImmutableAsList extends ImmutableAsList { - private final ImmutableCollection delegate; - private final ImmutableList delegateList; - - RegularImmutableAsList(ImmutableCollection delegate, ImmutableList delegateList) { - this.delegate = delegate; - this.delegateList = delegateList; - } - - RegularImmutableAsList(ImmutableCollection delegate, Object[] array) { - this(delegate, ImmutableList.asImmutableList(array)); - } - - @Override - ImmutableCollection delegateCollection() { - return delegate; - } - - ImmutableList delegateList() { - return delegateList; - } - - // safe covariant cast! - @Override - public UnmodifiableListIterator listIterator(int index) { - return (UnmodifiableListIterator) delegateList.listIterator(index); - } - - - @Override - int copyIntoArray(Object[] dst, int offset) { - return delegateList.copyIntoArray(dst, offset); - } - - @Override - public E get(int index) { - return delegateList.get(index); - } -} diff --git a/java/src/game/collect/RegularImmutableList.java b/java/src/game/collect/RegularImmutableList.java deleted file mode 100644 index e129981..0000000 --- a/java/src/game/collect/RegularImmutableList.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -/** - * Implementation of {@link ImmutableList} with one or more elements. - * - * @author Kevin Bourrillion - */ - - // uses writeReplace(), not default serialization -class RegularImmutableList extends ImmutableList { - private final transient int offset; - private final transient int size; - private final transient Object[] array; - - RegularImmutableList(Object[] array, int offset, int size) { - this.offset = offset; - this.size = size; - this.array = array; - } - - RegularImmutableList(Object[] array) { - this(array, 0, array.length); - } - - @Override - public int size() { - return size; - } - - @Override boolean isPartialView() { - return size != array.length; - } - - @Override - int copyIntoArray(Object[] dst, int dstOff) { - System.arraycopy(array, offset, dst, dstOff, size); - return dstOff + size; - } - - // The fake cast to E is safe because the creation methods only allow E's - @Override - - public E get(int index) { - Preconditions.checkElementIndex(index, size); - return (E) array[index + offset]; - } - - @Override - public int indexOf(Object object) { - if (object == null) { - return -1; - } - for (int i = 0; i < size; i++) { - if (array[offset + i].equals(object)) { - return i; - } - } - return -1; - } - - @Override - public int lastIndexOf(Object object) { - if (object == null) { - return -1; - } - for (int i = size - 1; i >= 0; i--) { - if (array[offset + i].equals(object)) { - return i; - } - } - return -1; - } - - @Override - ImmutableList subListUnchecked(int fromIndex, int toIndex) { - return new RegularImmutableList( - array, offset + fromIndex, toIndex - fromIndex); - } - - - @Override - public UnmodifiableListIterator listIterator(int index) { - // for performance - // The fake cast to E is safe because the creation methods only allow E's - return (UnmodifiableListIterator) - Iterators.forArray(array, offset, size, index); - } - - // TODO(user): benchmark optimizations for equals() and see if they're worthwhile -} diff --git a/java/src/game/collect/RegularImmutableMap.java b/java/src/game/collect/RegularImmutableMap.java deleted file mode 100644 index 81023b5..0000000 --- a/java/src/game/collect/RegularImmutableMap.java +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.CollectPreconditions.checkEntryNotNull; - -import game.collect.ImmutableMapEntry.TerminalEntry; - -/** - * Implementation of {@link ImmutableMap} with two or more entries. - * - * @author Jesse Wilson - * @author Kevin Bourrillion - * @author Gregory Kick - */ - -final class RegularImmutableMap extends ImmutableMap { - - // entries in insertion order - private final transient ImmutableMapEntry[] entries; - // array of linked lists of entries - private final transient ImmutableMapEntry[] table; - // 'and' with an int to get a table index - private final transient int mask; - - RegularImmutableMap(TerminalEntry... theEntries) { - this(theEntries.length, theEntries); - } - - /** - * Constructor for RegularImmutableMap that takes as input an array of {@code TerminalEntry} - * entries. Assumes that these entries have already been checked for null. - * - *

This allows reuse of the entry objects from the array in the actual implementation. - */ - RegularImmutableMap(int size, TerminalEntry[] theEntries) { - entries = createEntryArray(size); - int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR); - table = createEntryArray(tableSize); - mask = tableSize - 1; - for (int entryIndex = 0; entryIndex < size; entryIndex++) { - - TerminalEntry entry = (TerminalEntry) theEntries[entryIndex]; - K key = entry.getKey(); - int tableIndex = Hashing.smear(key.hashCode()) & mask; - ImmutableMapEntry existing = table[tableIndex]; - // prepend, not append, so the entries can be immutable - ImmutableMapEntry newEntry = (existing == null) - ? entry - : new NonTerminalMapEntry(entry, existing); - table[tableIndex] = newEntry; - entries[entryIndex] = newEntry; - checkNoConflictInBucket(key, newEntry, existing); - } - } - - /** - * Constructor for RegularImmutableMap that makes no assumptions about the input entries. - */ - RegularImmutableMap(Entry[] theEntries) { - int size = theEntries.length; - entries = createEntryArray(size); - int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR); - table = createEntryArray(tableSize); - mask = tableSize - 1; - for (int entryIndex = 0; entryIndex < size; entryIndex++) { - // all our callers carefully put in only Entrys - Entry entry = (Entry) theEntries[entryIndex]; - K key = entry.getKey(); - V value = entry.getValue(); - checkEntryNotNull(key, value); - int tableIndex = Hashing.smear(key.hashCode()) & mask; - ImmutableMapEntry existing = table[tableIndex]; - // prepend, not append, so the entries can be immutable - ImmutableMapEntry newEntry = (existing == null) - ? new TerminalEntry(key, value) - : new NonTerminalMapEntry(key, value, existing); - table[tableIndex] = newEntry; - entries[entryIndex] = newEntry; - checkNoConflictInBucket(key, newEntry, existing); - } - } - - private void checkNoConflictInBucket( - K key, ImmutableMapEntry entry, ImmutableMapEntry bucketHead) { - for (; bucketHead != null; bucketHead = bucketHead.getNextInKeyBucket()) { - checkNoConflict(!key.equals(bucketHead.getKey()), "key", entry, bucketHead); - } - } - - private static final class NonTerminalMapEntry extends ImmutableMapEntry { - private final ImmutableMapEntry nextInKeyBucket; - - NonTerminalMapEntry(K key, V value, ImmutableMapEntry nextInKeyBucket) { - super(key, value); - this.nextInKeyBucket = nextInKeyBucket; - } - - NonTerminalMapEntry(ImmutableMapEntry contents, ImmutableMapEntry nextInKeyBucket) { - super(contents); - this.nextInKeyBucket = nextInKeyBucket; - } - - @Override - ImmutableMapEntry getNextInKeyBucket() { - return nextInKeyBucket; - } - - @Override - - ImmutableMapEntry getNextInValueBucket() { - return null; - } - - } - - /** - * Closed addressing tends to perform well even with high load factors. - * Being conservative here ensures that the table is still likely to be - * relatively sparse (hence it misses fast) while saving space. - */ - private static final double MAX_LOAD_FACTOR = 1.2; - - /** - * Creates an {@code ImmutableMapEntry} array to hold parameterized entries. The - * result must never be upcast back to ImmutableMapEntry[] (or Object[], etc.), or - * allowed to escape the class. - */ - // Safe as long as the javadocs are followed - private ImmutableMapEntry[] createEntryArray(int size) { - return new ImmutableMapEntry[size]; - } - - @Override public V get(Object key) { - if (key == null) { - return null; - } - int index = Hashing.smear(key.hashCode()) & mask; - for (ImmutableMapEntry entry = table[index]; - entry != null; - entry = entry.getNextInKeyBucket()) { - K candidateKey = entry.getKey(); - - /* - * Assume that equals uses the == optimization when appropriate, and that - * it would check hash codes as an optimization when appropriate. If we - * did these things, it would just make things worse for the most - * performance-conscious users. - */ - if (key.equals(candidateKey)) { - return entry.getValue(); - } - } - return null; - } - - @Override - public int size() { - return entries.length; - } - - @Override boolean isPartialView() { - return false; - } - - @Override - ImmutableSet> createEntrySet() { - return new EntrySet(); - } - - // uses writeReplace(), not default serialization - private class EntrySet extends ImmutableMapEntrySet { - @Override ImmutableMap map() { - return RegularImmutableMap.this; - } - - @Override - public UnmodifiableIterator> iterator() { - return asList().iterator(); - } - - @Override - ImmutableList> createAsList() { - return new RegularImmutableAsList>(this, entries); - } - } - - // This class is never actually serialized directly, but we have to make the - // warning go away (and suppressing would suppress for all nested classes too) - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/collect/RegularImmutableSet.java b/java/src/game/collect/RegularImmutableSet.java deleted file mode 100644 index c10f204..0000000 --- a/java/src/game/collect/RegularImmutableSet.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -/** - * Implementation of {@link ImmutableSet} with two or more elements. - * - * @author Kevin Bourrillion - */ - - // uses writeReplace(), not default serialization -final class RegularImmutableSet extends ImmutableSet { - private final Object[] elements; - // the same elements in hashed positions (plus nulls) -// @VisibleForTesting - final transient Object[] table; - // 'and' with an int to get a valid table index. - private final transient int mask; - private final transient int hashCode; - - RegularImmutableSet( - Object[] elements, int hashCode, Object[] table, int mask) { - this.elements = elements; - this.table = table; - this.mask = mask; - this.hashCode = hashCode; - } - - @Override public boolean contains(Object target) { - if (target == null) { - return false; - } - for (int i = Hashing.smear(target.hashCode()); true; i++) { - Object candidate = table[i & mask]; - if (candidate == null) { - return false; - } - if (candidate.equals(target)) { - return true; - } - } - } - - @Override - public int size() { - return elements.length; - } - - // all elements are E's - @Override - public UnmodifiableIterator iterator() { - return (UnmodifiableIterator) Iterators.forArray(elements); - } - - @Override - int copyIntoArray(Object[] dst, int offset) { - System.arraycopy(elements, 0, dst, offset, elements.length); - return offset + elements.length; - } - - @Override - ImmutableList createAsList() { - return new RegularImmutableAsList(this, elements); - } - - @Override - boolean isPartialView() { - return false; - } - - @Override public int hashCode() { - return hashCode; - } - - @Override boolean isHashCodeFast() { - return true; - } -} diff --git a/java/src/game/collect/RegularImmutableTable.java b/java/src/game/collect/RegularImmutableTable.java deleted file mode 100644 index 9f48e21..0000000 --- a/java/src/game/collect/RegularImmutableTable.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkNotNull; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * An implementation of {@link ImmutableTable} holding an arbitrary number of - * cells. - * - * @author Gregory Kick - */ - -abstract class RegularImmutableTable extends ImmutableTable { - RegularImmutableTable() {} - - abstract Cell getCell(int iterationIndex); - - @Override - final ImmutableSet> createCellSet() { - return isEmpty() ? ImmutableSet.>of() : new CellSet(); - } - - private final class CellSet extends ImmutableSet> { - @Override - public int size() { - return RegularImmutableTable.this.size(); - } - - @Override - public UnmodifiableIterator> iterator() { - return asList().iterator(); - } - - @Override - ImmutableList> createAsList() { - return new ImmutableAsList>() { - @Override - public Cell get(int index) { - return getCell(index); - } - - @Override - ImmutableCollection> delegateCollection() { - return CellSet.this; - } - }; - } - - @Override - public boolean contains(Object object) { - if (object instanceof Cell) { - Cell cell = (Cell) object; - Object value = get(cell.getRowKey(), cell.getColumnKey()); - return value != null && value.equals(cell.getValue()); - } - return false; - } - - @Override - boolean isPartialView() { - return false; - } - } - - abstract V getValue(int iterationIndex); - - @Override - final ImmutableCollection createValues() { - return isEmpty() ? ImmutableList.of() : new Values(); - } - - private final class Values extends ImmutableList { - @Override - public int size() { - return RegularImmutableTable.this.size(); - } - - @Override - public V get(int index) { - return getValue(index); - } - - @Override - boolean isPartialView() { - return true; - } - } - - static RegularImmutableTable forCells( - List> cells, - final Comparator rowComparator, - final Comparator columnComparator) { - checkNotNull(cells); - if (rowComparator != null || columnComparator != null) { - /* - * This sorting logic leads to a cellSet() ordering that may not be expected and that isn't - * documented in the Javadoc. If a row Comparator is provided, cellSet() iterates across the - * columns in the first row, the columns in the second row, etc. If a column Comparator is - * provided but a row Comparator isn't, cellSet() iterates across the rows in the first - * column, the rows in the second column, etc. - */ - Comparator> comparator = new Comparator>() { - @Override public int compare(Cell cell1, Cell cell2) { - int rowCompare = (rowComparator == null) ? 0 - : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey()); - if (rowCompare != 0) { - return rowCompare; - } - return (columnComparator == null) ? 0 - : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey()); - } - }; - Collections.sort(cells, comparator); - } - return forCellsInternal(cells, rowComparator, columnComparator); - } - - static RegularImmutableTable forCells( - Iterable> cells) { - return forCellsInternal(cells, null, null); - } - - /** - * A factory that chooses the most space-efficient representation of the - * table. - */ - private static final RegularImmutableTable - forCellsInternal(Iterable> cells, - Comparator rowComparator, - Comparator columnComparator) { - ImmutableSet.Builder rowSpaceBuilder = ImmutableSet.builder(); - ImmutableSet.Builder columnSpaceBuilder = ImmutableSet.builder(); - ImmutableList> cellList = ImmutableList.copyOf(cells); - for (Cell cell : cellList) { - rowSpaceBuilder.add(cell.getRowKey()); - columnSpaceBuilder.add(cell.getColumnKey()); - } - - ImmutableSet rowSpace = rowSpaceBuilder.build(); - if (rowComparator != null) { - List rowList = Lists.newArrayList(rowSpace); - Collections.sort(rowList, rowComparator); - rowSpace = ImmutableSet.copyOf(rowList); - } - ImmutableSet columnSpace = columnSpaceBuilder.build(); - if (columnComparator != null) { - List columnList = Lists.newArrayList(columnSpace); - Collections.sort(columnList, columnComparator); - columnSpace = ImmutableSet.copyOf(columnList); - } - - // use a dense table if more than half of the cells have values - // TODO(gak): tune this condition based on empirical evidence - return (cellList.size() > (((long) rowSpace.size() * columnSpace.size()) / 2)) ? - new DenseImmutableTable(cellList, rowSpace, columnSpace) : - new SparseImmutableTable(cellList, rowSpace, columnSpace); - } -} diff --git a/java/src/game/collect/Sets.java b/java/src/game/collect/Sets.java deleted file mode 100644 index 04b2d4c..0000000 --- a/java/src/game/collect/Sets.java +++ /dev/null @@ -1,1607 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkNotNull; - -import java.util.AbstractSet; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.TreeSet; - -/** - * Static utility methods pertaining to {@link Set} instances. Also see this - * class's counterparts {@link Lists}, {@link Maps} and {@link Queues}. - * - *

See the Guava User Guide article on - * {@code Sets}. - * - * @author Kevin Bourrillion - * @author Jared Levy - * @author Chris Povirk - * @since 2.0 (imported from Google Collections Library) - */ - -public final class Sets { - private Sets() {} - - /** - * {@link AbstractSet} substitute without the potentially-quadratic - * {@code removeAll} implementation. - */ - abstract static class ImprovedAbstractSet extends AbstractSet { - @Override - public boolean removeAll(Collection c) { - return removeAllImpl(this, c); - } - - @Override - public boolean retainAll(Collection c) { - return super.retainAll(checkNotNull(c)); // GWT compatibility - } - } - - /** - * Returns an immutable set instance containing the given enum elements. - * Internally, the returned set will be backed by an {@link EnumSet}. - * - *

The iteration order of the returned set follows the enum's iteration - * order, not the order in which the elements are provided to the method. - * - * @param anElement one of the elements the set should contain - * @param otherElements the rest of the elements the set should contain - * @return an immutable set containing those elements, minus duplicates - */ - // http://code.google.com/p/google-web-toolkit/issues/detail?id=3028 -// -// public static > ImmutableSet immutableEnumSet( -// E anElement, E... otherElements) { -// return ImmutableEnumSet.asImmutable(EnumSet.of(anElement, otherElements)); -// } -// -// /** -// * Returns an immutable set instance containing the given enum elements. -// * Internally, the returned set will be backed by an {@link EnumSet}. -// * -// *

The iteration order of the returned set follows the enum's iteration -// * order, not the order in which the elements appear in the given collection. -// * -// * @param elements the elements, all of the same {@code enum} type, that the -// * set should contain -// * @return an immutable set containing those elements, minus duplicates -// */ -// // http://code.google.com/p/google-web-toolkit/issues/detail?id=3028 -// -// public static > ImmutableSet immutableEnumSet( -// Iterable elements) { -// if (elements instanceof ImmutableEnumSet) { -// return (ImmutableEnumSet) elements; -// } else if (elements instanceof Collection) { -// Collection collection = (Collection) elements; -// if (collection.isEmpty()) { -// return ImmutableSet.of(); -// } else { -// return ImmutableEnumSet.asImmutable(EnumSet.copyOf(collection)); -// } -// } else { -// Iterator itr = elements.iterator(); -// if (itr.hasNext()) { -// EnumSet enumSet = EnumSet.of(itr.next()); -// Iterators.addAll(enumSet, itr); -// return ImmutableEnumSet.asImmutable(enumSet); -// } else { -// return ImmutableSet.of(); -// } -// } -// } - - /** - * Returns a new {@code EnumSet} instance containing the given elements. - * Unlike {@link EnumSet#copyOf(Collection)}, this method does not produce an - * exception on an empty collection, and it may be called on any iterable, not - * just a {@code Collection}. - */ -// public static > EnumSet newEnumSet(Iterable iterable, -// Class elementType) { -// EnumSet set = EnumSet.noneOf(elementType); -// Iterables.addAll(set, iterable); -// return set; -// } - - // HashSet - - /** - * Creates a mutable, empty {@code HashSet} instance. - * - *

Note: if mutability is not required, use {@link - * ImmutableSet#of()} instead. - * - *

Note: if {@code E} is an {@link Enum} type, use {@link - * EnumSet#noneOf} instead. - * - * @return a new, empty {@code HashSet} - */ - public static HashSet newHashSet() { - return new HashSet(); - } - - /** - * Creates a mutable {@code HashSet} instance containing the given - * elements in unspecified order. - * - *

Note: if mutability is not required and the elements are - * non-null, use an overload of {@link ImmutableSet#of()} (for varargs) or - * {@link ImmutableSet#copyOf(Object[])} (for an array) instead. - * - *

Note: if {@code E} is an {@link Enum} type, use {@link - * EnumSet#of(Enum, Enum[])} instead. - * - * @param elements the elements that the set should contain - * @return a new {@code HashSet} containing those elements (minus duplicates) - */ - public static HashSet newHashSet(E... elements) { - HashSet set = newHashSetWithExpectedSize(elements.length); - Collections.addAll(set, elements); - return set; - } - - /** - * Creates a {@code HashSet} instance, with a high enough "initial capacity" - * that it should hold {@code expectedSize} elements without growth. - * This behavior cannot be broadly guaranteed, but it is observed to be true - * for OpenJDK 1.6. It also can't be guaranteed that the method isn't - * inadvertently oversizing the returned set. - * - * @param expectedSize the number of elements you expect to add to the - * returned set - * @return a new, empty {@code HashSet} with enough capacity to hold {@code - * expectedSize} elements without resizing - * @throws IllegalArgumentException if {@code expectedSize} is negative - */ - public static HashSet newHashSetWithExpectedSize(int expectedSize) { - return new HashSet(Maps.capacity(expectedSize)); - } - - /** - * Creates a mutable {@code HashSet} instance containing the given - * elements in unspecified order. - * - *

Note: if mutability is not required and the elements are - * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead. - * - *

Note: if {@code E} is an {@link Enum} type, use - * {@link #newEnumSet(Iterable, Class)} instead. - * - * @param elements the elements that the set should contain - * @return a new {@code HashSet} containing those elements (minus duplicates) - */ - public static HashSet newHashSet(Iterable elements) { - return (elements instanceof Collection) - ? new HashSet(Filter.cast(elements)) - : newHashSet(elements.iterator()); - } - - /** - * Creates a mutable {@code HashSet} instance containing the given - * elements in unspecified order. - * - *

Note: if mutability is not required and the elements are - * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead. - * - *

Note: if {@code E} is an {@link Enum} type, you should create an - * {@link EnumSet} instead. - * - * @param elements the elements that the set should contain - * @return a new {@code HashSet} containing those elements (minus duplicates) - */ - public static HashSet newHashSet(Iterator elements) { - HashSet set = newHashSet(); - Iterators.addAll(set, elements); - return set; - } - - - - /** - * Creates a thread-safe set backed by a hash map and containing the given - * elements. The set is backed by a {@link ConcurrentHashMap} instance, and - * thus carries the same concurrency guarantees. - * - *

Unlike {@code HashSet}, this class does NOT allow {@code null} to be - * used as an element. The set is serializable. - * - * @param elements the elements that the set should contain - * @return a new thread-safe set containing those elements (minus duplicates) - * @throws NullPointerException if {@code elements} or any of its contents is - * null - * @since 15.0 - */ -// public static Set newConcurrentHashSet( -// Iterable elements) { -// Set set = newConcurrentHashSet(); -// Iterables.addAll(set, elements); -// return set; -// } - - // LinkedHashSet - - - - /** - * Creates a {@code LinkedHashSet} instance, with a high enough "initial - * capacity" that it should hold {@code expectedSize} elements without - * growth. This behavior cannot be broadly guaranteed, but it is observed to - * be true for OpenJDK 1.6. It also can't be guaranteed that the method isn't - * inadvertently oversizing the returned set. - * - * @param expectedSize the number of elements you expect to add to the - * returned set - * @return a new, empty {@code LinkedHashSet} with enough capacity to hold - * {@code expectedSize} elements without resizing - * @throws IllegalArgumentException if {@code expectedSize} is negative - * @since 11.0 - */ -// public static LinkedHashSet newLinkedHashSetWithExpectedSize( -// int expectedSize) { -// return new LinkedHashSet(Maps.capacity(expectedSize)); -// } - - /** - * Creates a mutable {@code LinkedHashSet} instance containing the - * given elements in order. - * - *

Note: if mutability is not required and the elements are - * non-null, use {@link ImmutableSet#copyOf(Iterable)} instead. - * - * @param elements the elements that the set should contain, in order - * @return a new {@code LinkedHashSet} containing those elements (minus - * duplicates) - */ -// public static LinkedHashSet newLinkedHashSet( -// Iterable elements) { -// if (elements instanceof Collection) { -// return new LinkedHashSet(Collections2.cast(elements)); -// } -// LinkedHashSet set = newLinkedHashSet(); -// Iterables.addAll(set, elements); -// return set; -// } - - // TreeSet - - /** - * Creates a mutable, empty {@code TreeSet} instance sorted by the - * natural sort ordering of its elements. - * - *

Note: if mutability is not required, use {@link - * ImmutableSortedSet#of()} instead. - * - * @return a new, empty {@code TreeSet} - */ - public static TreeSet newTreeSet() { - return new TreeSet(); - } - - /** - * Creates a mutable {@code TreeSet} instance containing the given - * elements sorted by their natural ordering. - * - *

Note: if mutability is not required, use {@link - * ImmutableSortedSet#copyOf(Iterable)} instead. - * - *

Note: If {@code elements} is a {@code SortedSet} with an explicit - * comparator, this method has different behavior than - * {@link TreeSet#TreeSet(SortedSet)}, which returns a {@code TreeSet} with - * that comparator. - * - * @param elements the elements that the set should contain - * @return a new {@code TreeSet} containing those elements (minus duplicates) - */ -// public static TreeSet newTreeSet( -// Iterable elements) { -// TreeSet set = newTreeSet(); -// Iterables.addAll(set, elements); -// return set; -// } - - /** - * Creates a mutable, empty {@code TreeSet} instance with the given - * comparator. - * - *

Note: if mutability is not required, use {@code - * ImmutableSortedSet.orderedBy(comparator).build()} instead. - * - * @param comparator the comparator to use to sort the set - * @return a new, empty {@code TreeSet} - * @throws NullPointerException if {@code comparator} is null - */ -// public static TreeSet newTreeSet(Comparator comparator) { -// return new TreeSet(checkNotNull(comparator)); -// } - - - - /** - * Creates an empty {@code CopyOnWriteArraySet} instance. - * - *

Note: if you need an immutable empty {@link Set}, use - * {@link Collections#emptySet} instead. - * - * @return a new, empty {@code CopyOnWriteArraySet} - * @since 12.0 - */ -// -// public static CopyOnWriteArraySet newCopyOnWriteArraySet() { -// return new CopyOnWriteArraySet(); -// } -// -// /** -// * Creates a {@code CopyOnWriteArraySet} instance containing the given elements. -// * -// * @param elements the elements that the set should contain, in order -// * @return a new {@code CopyOnWriteArraySet} containing those elements -// * @since 12.0 -// */ -// -// public static CopyOnWriteArraySet newCopyOnWriteArraySet( -// Iterable elements) { -// // We copy elements to an ArrayList first, rather than incurring the -// // quadratic cost of adding them to the COWAS directly. -// Collection elementsCollection = (elements instanceof Collection) -// ? Collections2.cast(elements) -// : Lists.newArrayList(elements); -// return new CopyOnWriteArraySet(elementsCollection); -// } - - /** - * Creates an {@code EnumSet} consisting of all enum values that are not in - * the specified collection. If the collection is an {@link EnumSet}, this - * method has the same behavior as {@link EnumSet#complementOf}. Otherwise, - * the specified collection must contain at least one element, in order to - * determine the element type. If the collection could be empty, use - * {@link #complementOf(Collection, Class)} instead of this method. - * - * @param collection the collection whose complement should be stored in the - * enum set - * @return a new, modifiable {@code EnumSet} containing all values of the enum - * that aren't present in the given collection - * @throws IllegalArgumentException if {@code collection} is not an - * {@code EnumSet} instance and contains no elements - */ -// public static > EnumSet complementOf( -// Collection collection) { -// if (collection instanceof EnumSet) { -// return EnumSet.complementOf((EnumSet) collection); -// } -// checkArgument(!collection.isEmpty(), -// "collection is empty; use the other version of this method"); -// Class type = collection.iterator().next().getDeclaringClass(); -// return makeComplementByHand(collection, type); -// } - - /** - * Creates an {@code EnumSet} consisting of all enum values that are not in - * the specified collection. This is equivalent to - * {@link EnumSet#complementOf}, but can act on any input collection, as long - * as the elements are of enum type. - * - * @param collection the collection whose complement should be stored in the - * {@code EnumSet} - * @param type the type of the elements in the set - * @return a new, modifiable {@code EnumSet} initially containing all the - * values of the enum not present in the given collection - */ -// public static > EnumSet complementOf( -// Collection collection, Class type) { -// checkNotNull(collection); -// return (collection instanceof EnumSet) -// ? EnumSet.complementOf((EnumSet) collection) -// : makeComplementByHand(collection, type); -// } -// -// private static > EnumSet makeComplementByHand( -// Collection collection, Class type) { -// EnumSet result = EnumSet.allOf(type); -// result.removeAll(collection); -// return result; -// } - - /** - * An unmodifiable view of a set which may be backed by other sets; this view - * will change as the backing sets do. Contains methods to copy the data into - * a new set which will then remain stable. There is usually no reason to - * retain a reference of type {@code SetView}; typically, you either use it - * as a plain {@link Set}, or immediately invoke {@link #immutableCopy} or - * {@link #copyInto} and forget the {@code SetView} itself. - * - * @since 2.0 (imported from Google Collections Library) - */ -// public abstract static class SetView extends AbstractSet { -// private SetView() {} // no subclasses but our own -// -// /** -// * Returns an immutable copy of the current contents of this set view. -// * Does not support null elements. -// * -// *

Warning: this may have unexpected results if a backing set of -// * this view uses a nonstandard notion of equivalence, for example if it is -// * a {@link TreeSet} using a comparator that is inconsistent with {@link -// * Object#equals(Object)}. -// */ -// public ImmutableSet immutableCopy() { -// return ImmutableSet.copyOf(this); -// } -// -// /** -// * Copies the current contents of this set view into an existing set. This -// * method has equivalent behavior to {@code set.addAll(this)}, assuming that -// * all the sets involved are based on the same notion of equivalence. -// * -// * @return a reference to {@code set}, for convenience -// */ -// // Note: S should logically extend Set but can't due to either -// // some javac bug or some weirdness in the spec, not sure which. -// public > S copyInto(S set) { -// set.addAll(this); -// return set; -// } -// } - - /** - * Returns an unmodifiable view of the union of two sets. The returned - * set contains all elements that are contained in either backing set. - * Iterating over the returned set iterates first over all the elements of - * {@code set1}, then over each element of {@code set2}, in order, that is not - * contained in {@code set1}. - * - *

Results are undefined if {@code set1} and {@code set2} are sets based on - * different equivalence relations (as {@link HashSet}, {@link TreeSet}, and - * the {@link Map#keySet} of an {@code IdentityHashMap} all are). - * - *

Note: The returned view performs better when {@code set1} is the - * smaller of the two sets. If you have reason to believe one of your sets - * will generally be smaller than the other, pass it first. - * - *

Further, note that the current implementation is not suitable for nested - * {@code union} views, i.e. the following should be avoided when in a loop: - * {@code union = Sets.union(union, anotherSet);}, since iterating over the resulting - * set has a cubic complexity to the depth of the nesting. - */ -// public static SetView union( -// final Set set1, final Set set2) { -// checkNotNull(set1, "set1"); -// checkNotNull(set2, "set2"); -// -// final Set set2minus1 = difference(set2, set1); -// -// return new SetView() { -// @Override public int size() { -// return set1.size() + set2minus1.size(); -// } -// @Override public boolean isEmpty() { -// return set1.isEmpty() && set2.isEmpty(); -// } -// @Override public Iterator iterator() { -// return Iterators.unmodifiableIterator( -// Iterators.concat(set1.iterator(), set2minus1.iterator())); -// } -// @Override public boolean contains(Object object) { -// return set1.contains(object) || set2.contains(object); -// } -// @Override public > S copyInto(S set) { -// set.addAll(set1); -// set.addAll(set2); -// return set; -// } -// @Override public ImmutableSet immutableCopy() { -// return new ImmutableSet.Builder() -// .addAll(set1).addAll(set2).build(); -// } -// }; -// } - - /** - * Returns an unmodifiable view of the intersection of two sets. The - * returned set contains all elements that are contained by both backing sets. - * The iteration order of the returned set matches that of {@code set1}. - * - *

Results are undefined if {@code set1} and {@code set2} are sets based - * on different equivalence relations (as {@code HashSet}, {@code TreeSet}, - * and the keySet of an {@code IdentityHashMap} all are). - * - *

Note: The returned view performs slightly better when {@code - * set1} is the smaller of the two sets. If you have reason to believe one of - * your sets will generally be smaller than the other, pass it first. - * Unfortunately, since this method sets the generic type of the returned set - * based on the type of the first set passed, this could in rare cases force - * you to make a cast, for example:

   {@code
-   *
-   *   Set aFewBadObjects = ...
-   *   Set manyBadStrings = ...
-   *
-   *   // impossible for a non-String to be in the intersection
-   *   SuppressWarnings("unchecked")
-   *   Set badStrings = (Set) Sets.intersection(
-   *       aFewBadObjects, manyBadStrings);}
-   *
-   * 

This is unfortunate, but should come up only very rarely. - */ -// public static SetView intersection( -// final Set set1, final Set set2) { -// checkNotNull(set1, "set1"); -// checkNotNull(set2, "set2"); -// -// final Predicate inSet2 = Predicates.in(set2); -// return new SetView() { -// @Override public Iterator iterator() { -// return Iterators.filter(set1.iterator(), inSet2); -// } -// @Override public int size() { -// return Iterators.size(iterator()); -// } -// @Override public boolean isEmpty() { -// return !iterator().hasNext(); -// } -// @Override public boolean contains(Object object) { -// return set1.contains(object) && set2.contains(object); -// } -// @Override public boolean containsAll(Collection collection) { -// return set1.containsAll(collection) -// && set2.containsAll(collection); -// } -// }; -// } - - /** - * Returns an unmodifiable view of the difference of two sets. The - * returned set contains all elements that are contained by {@code set1} and - * not contained by {@code set2}. {@code set2} may also contain elements not - * present in {@code set1}; these are simply ignored. The iteration order of - * the returned set matches that of {@code set1}. - * - *

Results are undefined if {@code set1} and {@code set2} are sets based - * on different equivalence relations (as {@code HashSet}, {@code TreeSet}, - * and the keySet of an {@code IdentityHashMap} all are). - */ -// public static SetView difference( -// final Set set1, final Set set2) { -// checkNotNull(set1, "set1"); -// checkNotNull(set2, "set2"); -// -// final Predicate notInSet2 = Predicates.not(Predicates.in(set2)); -// return new SetView() { -// @Override public Iterator iterator() { -// return Iterators.filter(set1.iterator(), notInSet2); -// } -// @Override public int size() { -// return Iterators.size(iterator()); -// } -// @Override public boolean isEmpty() { -// return set2.containsAll(set1); -// } -// @Override public boolean contains(Object element) { -// return set1.contains(element) && !set2.contains(element); -// } -// }; -// } - - /** - * Returns an unmodifiable view of the symmetric difference of two - * sets. The returned set contains all elements that are contained in either - * {@code set1} or {@code set2} but not in both. The iteration order of the - * returned set is undefined. - * - *

Results are undefined if {@code set1} and {@code set2} are sets based - * on different equivalence relations (as {@code HashSet}, {@code TreeSet}, - * and the keySet of an {@code IdentityHashMap} all are). - * - * @since 3.0 - */ -// public static SetView symmetricDifference( -// Set set1, Set set2) { -// checkNotNull(set1, "set1"); -// checkNotNull(set2, "set2"); -// -// // TODO(kevinb): Replace this with a more efficient implementation -// return difference(union(set1, set2), intersection(set1, set2)); -// } - - /** - * Returns the elements of {@code unfiltered} that satisfy a predicate. The - * returned set is a live view of {@code unfiltered}; changes to one affect - * the other. - * - *

The resulting set's iterator does not support {@code remove()}, but all - * other set methods are supported. When given an element that doesn't satisfy - * the predicate, the set's {@code add()} and {@code addAll()} methods throw - * an {@link IllegalArgumentException}. When methods such as {@code - * removeAll()} and {@code clear()} are called on the filtered set, only - * elements that satisfy the filter will be removed from the underlying set. - * - *

The returned set isn't threadsafe or serializable, even if - * {@code unfiltered} is. - * - *

Many of the filtered set's methods, such as {@code size()}, iterate - * across every element in the underlying set and determine which elements - * satisfy the filter. When a live view is not needed, it may be faster - * to copy {@code Iterables.filter(unfiltered, predicate)} and use the copy. - * - *

Warning: {@code predicate} must be consistent with equals, - * as documented at {@link Predicate#apply}. Do not provide a predicate such - * as {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent - * with equals. (See {@link Iterables#filter(Iterable, Class)} for related - * functionality.) - */ - // TODO(kevinb): how to omit that last sentence when building GWT javadoc? -// public static Set filter( -// Set unfiltered, Predicate predicate) { -// if (unfiltered instanceof SortedSet) { -// return filter((SortedSet) unfiltered, predicate); -// } -// if (unfiltered instanceof FilteredSet) { -// // Support clear(), removeAll(), and retainAll() when filtering a filtered -// // collection. -// FilteredSet filtered = (FilteredSet) unfiltered; -// Predicate combinedPredicate -// = Predicates.and(filtered.predicate, predicate); -// return new FilteredSet( -// (Set) filtered.unfiltered, combinedPredicate); -// } -// -// return new FilteredSet( -// checkNotNull(unfiltered), checkNotNull(predicate)); -// } - -// private static class FilteredSet extends FilteredCollection -// implements Set { -// FilteredSet(Set unfiltered, Predicate predicate) { -// super(unfiltered, predicate); -// } -// -// @Override public boolean equals(Object object) { -// return equalsImpl(this, object); -// } -// -// @Override public int hashCode() { -// return hashCodeImpl(this); -// } -// } - - /** - * Returns the elements of a {@code SortedSet}, {@code unfiltered}, that - * satisfy a predicate. The returned set is a live view of {@code unfiltered}; - * changes to one affect the other. - * - *

The resulting set's iterator does not support {@code remove()}, but all - * other set methods are supported. When given an element that doesn't satisfy - * the predicate, the set's {@code add()} and {@code addAll()} methods throw - * an {@link IllegalArgumentException}. When methods such as - * {@code removeAll()} and {@code clear()} are called on the filtered set, - * only elements that satisfy the filter will be removed from the underlying - * set. - * - *

The returned set isn't threadsafe or serializable, even if - * {@code unfiltered} is. - * - *

Many of the filtered set's methods, such as {@code size()}, iterate across - * every element in the underlying set and determine which elements satisfy - * the filter. When a live view is not needed, it may be faster to copy - * {@code Iterables.filter(unfiltered, predicate)} and use the copy. - * - *

Warning: {@code predicate} must be consistent with equals, - * as documented at {@link Predicate#apply}. Do not provide a predicate such as - * {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent with - * equals. (See {@link Iterables#filter(Iterable, Class)} for related - * functionality.) - * - * @since 11.0 - */ -// public static SortedSet filter( -// SortedSet unfiltered, Predicate predicate) { -// return Platform.setsFilterSortedSet(unfiltered, predicate); -// } - -// static SortedSet filterSortedIgnoreNavigable( -// SortedSet unfiltered, Predicate predicate) { -// if (unfiltered instanceof FilteredSet) { -// // Support clear(), removeAll(), and retainAll() when filtering a filtered -// // collection. -// FilteredSet filtered = (FilteredSet) unfiltered; -// Predicate combinedPredicate -// = Predicates.and(filtered.predicate, predicate); -// return new FilteredSortedSet( -// (SortedSet) filtered.unfiltered, combinedPredicate); -// } -// -// return new FilteredSortedSet( -// checkNotNull(unfiltered), checkNotNull(predicate)); -// } -// -// private static class FilteredSortedSet extends FilteredSet -// implements SortedSet { -// -// FilteredSortedSet(SortedSet unfiltered, Predicate predicate) { -// super(unfiltered, predicate); -// } -// -// @Override -// public Comparator comparator() { -// return ((SortedSet) unfiltered).comparator(); -// } -// -// @Override -// public SortedSet subSet(E fromElement, E toElement) { -// return new FilteredSortedSet(((SortedSet) unfiltered).subSet(fromElement, toElement), -// predicate); -// } -// -// @Override -// public SortedSet headSet(E toElement) { -// return new FilteredSortedSet(((SortedSet) unfiltered).headSet(toElement), predicate); -// } -// -// @Override -// public SortedSet tailSet(E fromElement) { -// return new FilteredSortedSet(((SortedSet) unfiltered).tailSet(fromElement), predicate); -// } -// -// @Override -// public E first() { -// return iterator().next(); -// } -// -// @Override -// public E last() { -// SortedSet sortedUnfiltered = (SortedSet) unfiltered; -// while (true) { -// E element = sortedUnfiltered.last(); -// if (predicate.apply(element)) { -// return element; -// } -// sortedUnfiltered = sortedUnfiltered.headSet(element); -// } -// } -// } - - /** - * Returns the elements of a {@code NavigableSet}, {@code unfiltered}, that - * satisfy a predicate. The returned set is a live view of {@code unfiltered}; - * changes to one affect the other. - * - *

The resulting set's iterator does not support {@code remove()}, but all - * other set methods are supported. When given an element that doesn't satisfy - * the predicate, the set's {@code add()} and {@code addAll()} methods throw - * an {@link IllegalArgumentException}. When methods such as - * {@code removeAll()} and {@code clear()} are called on the filtered set, - * only elements that satisfy the filter will be removed from the underlying - * set. - * - *

The returned set isn't threadsafe or serializable, even if - * {@code unfiltered} is. - * - *

Many of the filtered set's methods, such as {@code size()}, iterate across - * every element in the underlying set and determine which elements satisfy - * the filter. When a live view is not needed, it may be faster to copy - * {@code Iterables.filter(unfiltered, predicate)} and use the copy. - * - *

Warning: {@code predicate} must be consistent with equals, - * as documented at {@link Predicate#apply}. Do not provide a predicate such as - * {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent with - * equals. (See {@link Iterables#filter(Iterable, Class)} for related - * functionality.) - * - * @since 14.0 - */ -// -// -// public static NavigableSet filter( -// NavigableSet unfiltered, Predicate predicate) { -// if (unfiltered instanceof FilteredSet) { -// // Support clear(), removeAll(), and retainAll() when filtering a filtered -// // collection. -// FilteredSet filtered = (FilteredSet) unfiltered; -// Predicate combinedPredicate -// = Predicates.and(filtered.predicate, predicate); -// return new FilteredNavigableSet( -// (NavigableSet) filtered.unfiltered, combinedPredicate); -// } -// -// return new FilteredNavigableSet( -// checkNotNull(unfiltered), checkNotNull(predicate)); -// } -// -// -// private static class FilteredNavigableSet extends FilteredSortedSet -// implements NavigableSet { -// FilteredNavigableSet(NavigableSet unfiltered, Predicate predicate) { -// super(unfiltered, predicate); -// } -// -// NavigableSet unfiltered() { -// return (NavigableSet) unfiltered; -// } -// -// @Override -// -// public E lower(E e) { -// return Iterators.getNext(headSet(e, false).descendingIterator(), null); -// } -// -// @Override -// -// public E floor(E e) { -// return Iterators.getNext(headSet(e, true).descendingIterator(), null); -// } -// -// @Override -// public E ceiling(E e) { -// return Iterables.getFirst(tailSet(e, true), null); -// } -// -// @Override -// public E higher(E e) { -// return Iterables.getFirst(tailSet(e, false), null); -// } -// -// @Override -// public E pollFirst() { -// return Iterables.removeFirstMatching(unfiltered(), predicate); -// } -// -// @Override -// public E pollLast() { -// return Iterables.removeFirstMatching(unfiltered().descendingSet(), predicate); -// } -// -// @Override -// public NavigableSet descendingSet() { -// return Sets.filter(unfiltered().descendingSet(), predicate); -// } -// -// @Override -// public Iterator descendingIterator() { -// return Iterators.filter(unfiltered().descendingIterator(), predicate); -// } -// -// @Override -// public E last() { -// return descendingIterator().next(); -// } -// -// @Override -// public NavigableSet subSet( -// E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { -// return filter( -// unfiltered().subSet(fromElement, fromInclusive, toElement, toInclusive), predicate); -// } -// -// @Override -// public NavigableSet headSet(E toElement, boolean inclusive) { -// return filter(unfiltered().headSet(toElement, inclusive), predicate); -// } -// -// @Override -// public NavigableSet tailSet(E fromElement, boolean inclusive) { -// return filter(unfiltered().tailSet(fromElement, inclusive), predicate); -// } -// } - - /** - * Returns every possible list that can be formed by choosing one element - * from each of the given sets in order; the "n-ary - * Cartesian - * product" of the sets. For example:

   {@code
-   *
-   *   Sets.cartesianProduct(ImmutableList.of(
-   *       ImmutableSet.of(1, 2),
-   *       ImmutableSet.of("A", "B", "C")))}
- * - *

returns a set containing six lists: - * - *

    - *
  • {@code ImmutableList.of(1, "A")} - *
  • {@code ImmutableList.of(1, "B")} - *
  • {@code ImmutableList.of(1, "C")} - *
  • {@code ImmutableList.of(2, "A")} - *
  • {@code ImmutableList.of(2, "B")} - *
  • {@code ImmutableList.of(2, "C")} - *
- * - *

The result is guaranteed to be in the "traditional", lexicographical - * order for Cartesian products that you would get from nesting for loops: - *

   {@code
-   *
-   *   for (B b0 : sets.get(0)) {
-   *     for (B b1 : sets.get(1)) {
-   *       ...
-   *       ImmutableList tuple = ImmutableList.of(b0, b1, ...);
-   *       // operate on tuple
-   *     }
-   *   }}
- * - *

Note that if any input set is empty, the Cartesian product will also be - * empty. If no sets at all are provided (an empty list), the resulting - * Cartesian product has one element, an empty list (counter-intuitive, but - * mathematically consistent). - * - *

Performance notes: while the cartesian product of sets of size - * {@code m, n, p} is a set of size {@code m x n x p}, its actual memory - * consumption is much smaller. When the cartesian set is constructed, the - * input sets are merely copied. Only as the resulting set is iterated are the - * individual lists created, and these are not retained after iteration. - * - * @param sets the sets to choose elements from, in the order that - * the elements chosen from those sets should appear in the resulting - * lists - * @param any common base class shared by all axes (often just {@link - * Object}) - * @return the Cartesian product, as an immutable set containing immutable - * lists - * @throws NullPointerException if {@code sets}, any one of the {@code sets}, - * or any element of a provided set is null - * @since 2.0 - */ -// public static Set> cartesianProduct( -// List> sets) { -// return CartesianSet.create(sets); -// } - - /** - * Returns every possible list that can be formed by choosing one element - * from each of the given sets in order; the "n-ary - * Cartesian - * product" of the sets. For example:

   {@code
-   *
-   *   Sets.cartesianProduct(
-   *       ImmutableSet.of(1, 2),
-   *       ImmutableSet.of("A", "B", "C"))}
- * - *

returns a set containing six lists: - * - *

    - *
  • {@code ImmutableList.of(1, "A")} - *
  • {@code ImmutableList.of(1, "B")} - *
  • {@code ImmutableList.of(1, "C")} - *
  • {@code ImmutableList.of(2, "A")} - *
  • {@code ImmutableList.of(2, "B")} - *
  • {@code ImmutableList.of(2, "C")} - *
- * - *

The result is guaranteed to be in the "traditional", lexicographical - * order for Cartesian products that you would get from nesting for loops: - *

   {@code
-   *
-   *   for (B b0 : sets.get(0)) {
-   *     for (B b1 : sets.get(1)) {
-   *       ...
-   *       ImmutableList tuple = ImmutableList.of(b0, b1, ...);
-   *       // operate on tuple
-   *     }
-   *   }}
- * - *

Note that if any input set is empty, the Cartesian product will also be - * empty. If no sets at all are provided (an empty list), the resulting - * Cartesian product has one element, an empty list (counter-intuitive, but - * mathematically consistent). - * - *

Performance notes: while the cartesian product of sets of size - * {@code m, n, p} is a set of size {@code m x n x p}, its actual memory - * consumption is much smaller. When the cartesian set is constructed, the - * input sets are merely copied. Only as the resulting set is iterated are the - * individual lists created, and these are not retained after iteration. - * - * @param sets the sets to choose elements from, in the order that - * the elements chosen from those sets should appear in the resulting - * lists - * @param any common base class shared by all axes (often just {@link - * Object}) - * @return the Cartesian product, as an immutable set containing immutable - * lists - * @throws NullPointerException if {@code sets}, any one of the {@code sets}, - * or any element of a provided set is null - * @since 2.0 - */ -// public static Set> cartesianProduct( -// Set... sets) { -// return cartesianProduct(Arrays.asList(sets)); -// } -// -// private static final class CartesianSet -// extends ForwardingCollection> implements Set> { -// private transient final ImmutableList> axes; -// private transient final CartesianList delegate; -// -// static Set> create(List> sets) { -// ImmutableList.Builder> axesBuilder = -// new ImmutableList.Builder>(sets.size()); -// for (Set set : sets) { -// ImmutableSet copy = ImmutableSet.copyOf(set); -// if (copy.isEmpty()) { -// return ImmutableSet.of(); -// } -// axesBuilder.add(copy); -// } -// final ImmutableList> axes = axesBuilder.build(); -// ImmutableList> listAxes = new ImmutableList>() { -// -// @Override -// public int size() { -// return axes.size(); -// } -// -// @Override -// public List get(int index) { -// return axes.get(index).asList(); -// } -// -// @Override -// boolean isPartialView() { -// return true; -// } -// }; -// return new CartesianSet(axes, new CartesianList(listAxes)); -// } -// -// private CartesianSet( -// ImmutableList> axes, CartesianList delegate) { -// this.axes = axes; -// this.delegate = delegate; -// } -// -// @Override -// protected Collection> delegate() { -// return delegate; -// } -// -// @Override public boolean equals(Object object) { -// // Warning: this is broken if size() == 0, so it is critical that we -// // substitute an empty ImmutableSet to the user in place of this -// if (object instanceof CartesianSet) { -// CartesianSet that = (CartesianSet) object; -// return this.axes.equals(that.axes); -// } -// return super.equals(object); -// } -// -// @Override -// public int hashCode() { -// // Warning: this is broken if size() == 0, so it is critical that we -// // substitute an empty ImmutableSet to the user in place of this -// -// // It's a weird formula, but tests prove it works. -// int adjust = size() - 1; -// for (int i = 0; i < axes.size(); i++) { -// adjust *= 31; -// adjust = ~~adjust; -// // in GWT, we have to deal with integer overflow carefully -// } -// int hash = 1; -// for (Set axis : axes) { -// hash = 31 * hash + (size() / axis.size() * axis.hashCode()); -// -// hash = ~~hash; -// } -// hash += adjust; -// return ~~hash; -// } -// } - - /** - * Returns the set of all possible subsets of {@code set}. For example, - * {@code powerSet(ImmutableSet.of(1, 2))} returns the set {@code {{}, - * {1}, {2}, {1, 2}}}. - * - *

Elements appear in these subsets in the same iteration order as they - * appeared in the input set. The order in which these subsets appear in the - * outer set is undefined. Note that the power set of the empty set is not the - * empty set, but a one-element set containing the empty set. - * - *

The returned set and its constituent sets use {@code equals} to decide - * whether two elements are identical, even if the input set uses a different - * concept of equivalence. - * - *

Performance notes: while the power set of a set with size {@code - * n} is of size {@code 2^n}, its memory usage is only {@code O(n)}. When the - * power set is constructed, the input set is merely copied. Only as the - * power set is iterated are the individual subsets created, and these subsets - * themselves occupy only a small constant amount of memory. - * - * @param set the set of elements to construct a power set from - * @return the power set, as an immutable set of immutable sets - * @throws IllegalArgumentException if {@code set} has more than 30 unique - * elements (causing the power set size to exceed the {@code int} range) - * @throws NullPointerException if {@code set} is or contains {@code null} - * @see Power set article at - * Wikipedia - * @since 4.0 - */ -// -// public static Set> powerSet(Set set) { -// return new PowerSet(set); -// } - -// private static final class SubSet extends AbstractSet { -// private final ImmutableMap inputSet; -// private final int mask; -// -// SubSet(ImmutableMap inputSet, int mask) { -// this.inputSet = inputSet; -// this.mask = mask; -// } -// -// @Override -// public Iterator iterator() { -// return new UnmodifiableIterator() { -// final ImmutableList elements = inputSet.keySet().asList(); -// int remainingSetBits = mask; -// -// @Override -// public boolean hasNext() { -// return remainingSetBits != 0; -// } -// -// @Override -// public E next() { -// int index = Integer.numberOfTrailingZeros(remainingSetBits); -// if (index == 32) { -// throw new NoSuchElementException(); -// } -// remainingSetBits &= ~(1 << index); -// return elements.get(index); -// } -// }; -// } -// -// @Override -// public int size() { -// return Integer.bitCount(mask); -// } -// -// @Override -// public boolean contains(Object o) { -// Integer index = inputSet.get(o); -// return index != null && (mask & (1 << index)) != 0; -// } -// } - -// private static final class PowerSet extends AbstractSet> { -// final ImmutableMap inputSet; -// -// PowerSet(Set input) { -// ImmutableMap.Builder builder = ImmutableMap.builder(); -// int i = 0; -// for (E e : checkNotNull(input)) { -// builder.put(e, i++); -// } -// this.inputSet = builder.build(); -// checkArgument(inputSet.size() <= 30, -// "Too many elements to create power set: %s > 30", inputSet.size()); -// } -// -// @Override public int size() { -// return 1 << inputSet.size(); -// } -// -// @Override public boolean isEmpty() { -// return false; -// } -// -// @Override public Iterator> iterator() { -// return new AbstractIndexedListIterator>(size()) { -// @Override protected Set get(final int setBits) { -// return new SubSet(inputSet, setBits); -// } -// }; -// } -// -// @Override public boolean contains(Object obj) { -// if (obj instanceof Set) { -// Set set = (Set) obj; -// return inputSet.keySet().containsAll(set); -// } -// return false; -// } -// -// @Override public boolean equals(Object obj) { -// if (obj instanceof PowerSet) { -// PowerSet that = (PowerSet) obj; -// return inputSet.equals(that.inputSet); -// } -// return super.equals(obj); -// } -// -// @Override public int hashCode() { -// /* -// * The sum of the sums of the hash codes in each subset is just the sum of -// * each input element's hash code times the number of sets that element -// * appears in. Each element appears in exactly half of the 2^n sets, so: -// */ -// return inputSet.keySet().hashCode() << (inputSet.size() - 1); -// } -// -// @Override public String toString() { -// return "powerSet(" + inputSet + ")"; -// } -// } - - /** - * An implementation for {@link Set#hashCode()}. - */ - static int hashCodeImpl(Set s) { - int hashCode = 0; - for (Object o : s) { - hashCode += o != null ? o.hashCode() : 0; - - hashCode = ~~hashCode; - // Needed to deal with unusual integer overflow in GWT. - } - return hashCode; - } - - /** - * An implementation for {@link Set#equals(Object)}. - */ - static boolean equalsImpl(Set s, Object object) { - if (s == object) { - return true; - } - if (object instanceof Set) { - Set o = (Set) object; - - try { - return s.size() == o.size() && s.containsAll(o); - } catch (NullPointerException ignored) { - return false; - } catch (ClassCastException ignored) { - return false; - } - } - return false; - } - - /** - * Returns an unmodifiable view of the specified navigable set. This method - * allows modules to provide users with "read-only" access to internal - * navigable sets. Query operations on the returned set "read through" to the - * specified set, and attempts to modify the returned set, whether direct or - * via its collection views, result in an - * {@code UnsupportedOperationException}. - * - *

The returned navigable set will be serializable if the specified - * navigable set is serializable. - * - * @param set the navigable set for which an unmodifiable view is to be - * returned - * @return an unmodifiable view of the specified navigable set - * @since 12.0 - */ -// -// public static NavigableSet unmodifiableNavigableSet( -// NavigableSet set) { -// if (set instanceof ImmutableSortedSet -// || set instanceof UnmodifiableNavigableSet) { -// return set; -// } -// return new UnmodifiableNavigableSet(set); -// } -// -// -// static final class UnmodifiableNavigableSet -// extends ForwardingSortedSet implements NavigableSet, Serializable { -// private final NavigableSet delegate; -// -// UnmodifiableNavigableSet(NavigableSet delegate) { -// this.delegate = checkNotNull(delegate); -// } -// -// @Override -// protected SortedSet delegate() { -// return Collections.unmodifiableSortedSet(delegate); -// } -// -// @Override -// public E lower(E e) { -// return delegate.lower(e); -// } -// -// @Override -// public E floor(E e) { -// return delegate.floor(e); -// } -// -// @Override -// public E ceiling(E e) { -// return delegate.ceiling(e); -// } -// -// @Override -// public E higher(E e) { -// return delegate.higher(e); -// } -// -// @Override -// public E pollFirst() { -// throw new UnsupportedOperationException(); -// } -// -// @Override -// public E pollLast() { -// throw new UnsupportedOperationException(); -// } -// -// private transient UnmodifiableNavigableSet descendingSet; -// -// @Override -// public NavigableSet descendingSet() { -// UnmodifiableNavigableSet result = descendingSet; -// if (result == null) { -// result = descendingSet = new UnmodifiableNavigableSet( -// delegate.descendingSet()); -// result.descendingSet = this; -// } -// return result; -// } -// -// @Override -// public Iterator descendingIterator() { -// return Iterators.unmodifiableIterator(delegate.descendingIterator()); -// } -// -// @Override -// public NavigableSet subSet( -// E fromElement, -// boolean fromInclusive, -// E toElement, -// boolean toInclusive) { -// return unmodifiableNavigableSet(delegate.subSet( -// fromElement, -// fromInclusive, -// toElement, -// toInclusive)); -// } -// -// @Override -// public NavigableSet headSet(E toElement, boolean inclusive) { -// return unmodifiableNavigableSet(delegate.headSet(toElement, inclusive)); -// } -// -// @Override -// public NavigableSet tailSet(E fromElement, boolean inclusive) { -// return unmodifiableNavigableSet( -// delegate.tailSet(fromElement, inclusive)); -// } -// -// private static final long serialVersionUID = 0; -// } - - /** - * Returns a synchronized (thread-safe) navigable set backed by the specified - * navigable set. In order to guarantee serial access, it is critical that - * all access to the backing navigable set is accomplished - * through the returned navigable set (or its views). - * - *

It is imperative that the user manually synchronize on the returned - * sorted set when iterating over it or any of its {@code descendingSet}, - * {@code subSet}, {@code headSet}, or {@code tailSet} views.

   {@code
-   *
-   *   NavigableSet set = synchronizedNavigableSet(new TreeSet());
-   *    ...
-   *   synchronized (set) {
-   *     // Must be in the synchronized block
-   *     Iterator it = set.iterator();
-   *     while (it.hasNext()) {
-   *       foo(it.next());
-   *     }
-   *   }}
- * - *

or:

   {@code
-   *
-   *   NavigableSet set = synchronizedNavigableSet(new TreeSet());
-   *   NavigableSet set2 = set.descendingSet().headSet(foo);
-   *    ...
-   *   synchronized (set) { // Note: set, not set2!!!
-   *     // Must be in the synchronized block
-   *     Iterator it = set2.descendingIterator();
-   *     while (it.hasNext())
-   *       foo(it.next());
-   *     }
-   *   }}
- * - *

Failure to follow this advice may result in non-deterministic behavior. - * - *

The returned navigable set will be serializable if the specified - * navigable set is serializable. - * - * @param navigableSet the navigable set to be "wrapped" in a synchronized - * navigable set. - * @return a synchronized view of the specified navigable set. - * @since 13.0 - */ -// -// public static NavigableSet synchronizedNavigableSet( -// NavigableSet navigableSet) { -// return Synchronized.navigableSet(navigableSet); -// } - - /** - * Remove each element in an iterable from a set. - */ - static boolean removeAllImpl(Set set, Iterator iterator) { - boolean changed = false; - while (iterator.hasNext()) { - changed |= set.remove(iterator.next()); - } - return changed; - } - - static boolean removeAllImpl(Set set, Collection collection) { - checkNotNull(collection); // for GWT -// if (collection instanceof Multiset) { -// collection = ((Multiset) collection).elementSet(); -// } - /* - * AbstractSet.removeAll(List) has quadratic behavior if the list size - * is just less than the set's size. We augment the test by - * assuming that sets have fast contains() performance, and other - * collections don't. See - * http://code.google.com/p/guava-libraries/issues/detail?id=1013 - */ - if (collection instanceof Set && collection.size() > set.size()) { - return Iterators.removeAll(set.iterator(), collection); - } else { - return removeAllImpl(set, collection.iterator()); - } - } - -// -// static class DescendingSet extends ForwardingNavigableSet { -// private final NavigableSet forward; -// -// DescendingSet(NavigableSet forward) { -// this.forward = forward; -// } -// -// @Override -// protected NavigableSet delegate() { -// return forward; -// } -// -// @Override -// public E lower(E e) { -// return forward.higher(e); -// } -// -// @Override -// public E floor(E e) { -// return forward.ceiling(e); -// } -// -// @Override -// public E ceiling(E e) { -// return forward.floor(e); -// } -// -// @Override -// public E higher(E e) { -// return forward.lower(e); -// } -// -// @Override -// public E pollFirst() { -// return forward.pollLast(); -// } -// -// @Override -// public E pollLast() { -// return forward.pollFirst(); -// } -// -// @Override -// public NavigableSet descendingSet() { -// return forward; -// } -// -// @Override -// public Iterator descendingIterator() { -// return forward.iterator(); -// } -// -// @Override -// public NavigableSet subSet( -// E fromElement, -// boolean fromInclusive, -// E toElement, -// boolean toInclusive) { -// return forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet(); -// } -// -// @Override -// public NavigableSet headSet(E toElement, boolean inclusive) { -// return forward.tailSet(toElement, inclusive).descendingSet(); -// } -// -// @Override -// public NavigableSet tailSet(E fromElement, boolean inclusive) { -// return forward.headSet(fromElement, inclusive).descendingSet(); -// } -// -// -// @Override -// public Comparator comparator() { -// Comparator forwardComparator = forward.comparator(); -// if (forwardComparator == null) { -// return (Comparator) Ordering.natural().reverse(); -// } else { -// return reverse(forwardComparator); -// } -// } -// -// // If we inline this, we get a javac error. -// private static Ordering reverse(Comparator forward) { -// return Ordering.from(forward).reverse(); -// } -// -// @Override -// public E first() { -// return forward.last(); -// } -// -// @Override -// public SortedSet headSet(E toElement) { -// return standardHeadSet(toElement); -// } -// -// @Override -// public E last() { -// return forward.first(); -// } -// -// @Override -// public SortedSet subSet(E fromElement, E toElement) { -// return standardSubSet(fromElement, toElement); -// } -// -// @Override -// public SortedSet tailSet(E fromElement) { -// return standardTailSet(fromElement); -// } -// -// @Override -// public Iterator iterator() { -// return forward.descendingIterator(); -// } -// -// @Override -// public Object[] toArray() { -// return standardToArray(); -// } -// -// @Override -// public T[] toArray(T[] array) { -// return standardToArray(array); -// } -// -// @Override -// public String toString() { -// return standardToString(); -// } -// } -} diff --git a/java/src/game/collect/SparseImmutableTable.java b/java/src/game/collect/SparseImmutableTable.java deleted file mode 100644 index 4c1d867..0000000 --- a/java/src/game/collect/SparseImmutableTable.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package game.collect; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * A {@code RegularImmutableTable} optimized for sparse data. - */ - -//@Immutable -final class SparseImmutableTable - extends RegularImmutableTable { - - private final ImmutableMap> rowMap; - private final ImmutableMap> columnMap; - private final int[] iterationOrderRow; - private final int[] iterationOrderColumn; - - SparseImmutableTable(ImmutableList> cellList, - ImmutableSet rowSpace, ImmutableSet columnSpace) { - Map rowIndex = Maps.newHashMap(); - Map> rows = Maps.newLinkedHashMap(); - for (R row : rowSpace) { - rowIndex.put(row, rows.size()); - rows.put(row, new LinkedHashMap()); - } - Map> columns = Maps.newLinkedHashMap(); - for (C col : columnSpace) { - columns.put(col, new LinkedHashMap()); - } - int[] iterationOrderRow = new int[cellList.size()]; - int[] iterationOrderColumn = new int[cellList.size()]; - for (int i = 0; i < cellList.size(); i++) { - Cell cell = cellList.get(i); - R rowKey = cell.getRowKey(); - C columnKey = cell.getColumnKey(); - V value = cell.getValue(); - - iterationOrderRow[i] = rowIndex.get(rowKey); - Map thisRow = rows.get(rowKey); - iterationOrderColumn[i] = thisRow.size(); - V oldValue = thisRow.put(columnKey, value); - if (oldValue != null) { - throw new IllegalArgumentException("Duplicate value for row=" + rowKey + ", column=" - + columnKey + ": " + value + ", " + oldValue); - } - columns.get(columnKey).put(rowKey, value); - } - this.iterationOrderRow = iterationOrderRow; - this.iterationOrderColumn = iterationOrderColumn; - ImmutableMap.Builder> rowBuilder = ImmutableMap.builder(); - for (Map.Entry> row : rows.entrySet()) { - rowBuilder.put(row.getKey(), ImmutableMap.copyOf(row.getValue())); - } - this.rowMap = rowBuilder.build(); - - ImmutableMap.Builder> columnBuilder = ImmutableMap.builder(); - for (Map.Entry> col : columns.entrySet()) { - columnBuilder.put(col.getKey(), ImmutableMap.copyOf(col.getValue())); - } - this.columnMap = columnBuilder.build(); - } - - @Override public ImmutableMap> columnMap() { - return columnMap; - } - - @Override public ImmutableMap> rowMap() { - return rowMap; - } - - @Override - public int size() { - return iterationOrderRow.length; - } - - @Override - Cell getCell(int index) { - int rowIndex = iterationOrderRow[index]; - Map.Entry> rowEntry = rowMap.entrySet().asList().get(rowIndex); - ImmutableMap row = (ImmutableMap) rowEntry.getValue(); - int columnIndex = iterationOrderColumn[index]; - Map.Entry colEntry = row.entrySet().asList().get(columnIndex); - return cellOf(rowEntry.getKey(), colEntry.getKey(), colEntry.getValue()); - } - - @Override - V getValue(int index) { - int rowIndex = iterationOrderRow[index]; - ImmutableMap row = (ImmutableMap) rowMap.values().asList().get(rowIndex); - int columnIndex = iterationOrderColumn[index]; - return row.values().asList().get(columnIndex); - } -} diff --git a/java/src/game/collect/StandardTable.java b/java/src/game/collect/StandardTable.java deleted file mode 100644 index 0f4d1c8..0000000 --- a/java/src/game/collect/StandardTable.java +++ /dev/null @@ -1,891 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Maps.safeContainsKey; -import static game.collect.Maps.safeGet; -import static game.collect.Preconditions.checkNotNull; -import static game.util.Predicates.alwaysTrue; -import static game.util.Predicates.equalTo; -import static game.util.Predicates.in; -import static game.util.Predicates.not; - -import java.io.Serializable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; - -import game.collect.Maps.ImprovedAbstractMap; -import game.collect.Sets.ImprovedAbstractSet; - -/** - * {@link Table} implementation backed by a map that associates row keys with - * column key / value secondary maps. This class provides rapid access to - * records by the row key alone or by both keys, but not by just the column key. - * - *

The views returned by {@link #column}, {@link #columnKeySet()}, and {@link - * #columnMap()} have iterators that don't support {@code remove()}. Otherwise, - * all optional operations are supported. Null row keys, columns keys, and - * values are not supported. - * - *

Lookups by row key are often faster than lookups by column key, because - * the data is stored in a {@code Map>}. A method call like {@code - * column(columnKey).get(rowKey)} still runs quickly, since the row key is - * provided. However, {@code column(columnKey).size()} takes longer, since an - * iteration across all row keys occurs. - * - *

Note that this implementation is not synchronized. If multiple threads - * access this table concurrently and one of the threads modifies the table, it - * must be synchronized externally. - * - * @author Jared Levy - */ - -public class StandardTable extends AbstractTable implements Serializable { - final Map> backingMap = new HashMap>(); -// final Supplier> factory; - -// StandardTable(Map> backingMap) { -// this.backingMap = backingMap; -//// this.factory = factory; -// } - - // Accessors - - @Override public boolean contains( - Object rowKey, Object columnKey) { - return rowKey != null && columnKey != null && super.contains(rowKey, columnKey); - } - - @Override public boolean containsColumn(Object columnKey) { - if (columnKey == null) { - return false; - } - for (Map map : backingMap.values()) { - if (safeContainsKey(map, columnKey)) { - return true; - } - } - return false; - } - - @Override public boolean containsRow(Object rowKey) { - return rowKey != null && safeContainsKey(backingMap, rowKey); - } - - @Override public boolean containsValue(Object value) { - return value != null && super.containsValue(value); - } - - @Override public V get(Object rowKey, Object columnKey) { - return (rowKey == null || columnKey == null) - ? null - : super.get(rowKey, columnKey); - } - - @Override public boolean isEmpty() { - return backingMap.isEmpty(); - } - - @Override public int size() { - int size = 0; - for (Map map : backingMap.values()) { - size += map.size(); - } - return size; - } - - // Mutators - - @Override public void clear() { - backingMap.clear(); - } - - private Map getOrCreate(R rowKey) { - Map map = backingMap.get(rowKey); - if (map == null) { - map = Maps.newHashMapWithExpectedSize(0); -// map = factory.get(); - backingMap.put(rowKey, map); - } - return map; - } - - @Override public V put(R rowKey, C columnKey, V value) { - checkNotNull(rowKey); - checkNotNull(columnKey); - checkNotNull(value); - return getOrCreate(rowKey).put(columnKey, value); - } - - @Override public V remove( - Object rowKey, Object columnKey) { - if ((rowKey == null) || (columnKey == null)) { - return null; - } - Map map = safeGet(backingMap, rowKey); - if (map == null) { - return null; - } - V value = map.remove(columnKey); - if (map.isEmpty()) { - backingMap.remove(rowKey); - } - return value; - } - - private Map removeColumn(Object column) { - Map output = new LinkedHashMap(); - Iterator>> iterator - = backingMap.entrySet().iterator(); - while (iterator.hasNext()) { - Entry> entry = iterator.next(); - V value = entry.getValue().remove(column); - if (value != null) { - output.put(entry.getKey(), value); - if (entry.getValue().isEmpty()) { - iterator.remove(); - } - } - } - return output; - } - - private boolean containsMapping( - Object rowKey, Object columnKey, Object value) { - return value != null && value.equals(get(rowKey, columnKey)); - } - - /** Remove a row key / column key / value mapping, if present. */ - private boolean removeMapping(Object rowKey, Object columnKey, Object value) { - if (containsMapping(rowKey, columnKey, value)) { - remove(rowKey, columnKey); - return true; - } - return false; - } - - // Views - - /** - * Abstract set whose {@code isEmpty()} returns whether the table is empty and - * whose {@code clear()} clears all table mappings. - */ - private abstract class TableSet extends ImprovedAbstractSet { - @Override public boolean isEmpty() { - return backingMap.isEmpty(); - } - - @Override public void clear() { - backingMap.clear(); - } - } - - /** - * {@inheritDoc} - * - *

The set's iterator traverses the mappings for the first row, the - * mappings for the second row, and so on. - * - *

Each cell is an immutable snapshot of a row key / column key / value - * mapping, taken at the time the cell is returned by a method call to the - * set or its iterator. - */ - @Override public Set> cellSet() { - return super.cellSet(); - } - - @Override Iterator> cellIterator() { - return new CellIterator(); - } - - private class CellIterator implements Iterator> { - final Iterator>> rowIterator - = backingMap.entrySet().iterator(); - Entry> rowEntry; - Iterator> columnIterator - = Iterators.emptyModifiableIterator(); - - @Override public boolean hasNext() { - return rowIterator.hasNext() || columnIterator.hasNext(); - } - - @Override public Cell next() { - if (!columnIterator.hasNext()) { - rowEntry = rowIterator.next(); - columnIterator = rowEntry.getValue().entrySet().iterator(); - } - Entry columnEntry = columnIterator.next(); - return ImmutableTable.immutableCell( - rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue()); - } - - @Override public void remove() { - columnIterator.remove(); - if (rowEntry.getValue().isEmpty()) { - rowIterator.remove(); - } - } - } - - @Override public Map row(R rowKey) { - return new Row(rowKey); - } - - class Row extends ImprovedAbstractMap { - final R rowKey; - - Row(R rowKey) { - this.rowKey = checkNotNull(rowKey); - } - - Map backingRowMap; - - Map backingRowMap() { - return (backingRowMap == null - || (backingRowMap.isEmpty() && backingMap.containsKey(rowKey))) - ? backingRowMap = computeBackingRowMap() - : backingRowMap; - } - - Map computeBackingRowMap() { - return backingMap.get(rowKey); - } - - // Call this every time we perform a removal. - void maintainEmptyInvariant() { - if (backingRowMap() != null && backingRowMap.isEmpty()) { - backingMap.remove(rowKey); - backingRowMap = null; - } - } - - @Override - public boolean containsKey(Object key) { - Map backingRowMap = backingRowMap(); - return (key != null && backingRowMap != null) - && Maps.safeContainsKey(backingRowMap, key); - } - - @Override - public V get(Object key) { - Map backingRowMap = backingRowMap(); - return (key != null && backingRowMap != null) - ? Maps.safeGet(backingRowMap, key) - : null; - } - - @Override - public V put(C key, V value) { - checkNotNull(key); - checkNotNull(value); - if (backingRowMap != null && !backingRowMap.isEmpty()) { - return backingRowMap.put(key, value); - } - return StandardTable.this.put(rowKey, key, value); - } - - @Override - public V remove(Object key) { - Map backingRowMap = backingRowMap(); - if (backingRowMap == null) { - return null; - } - V result = Maps.safeRemove(backingRowMap, key); - maintainEmptyInvariant(); - return result; - } - - @Override - public void clear() { - Map backingRowMap = backingRowMap(); - if (backingRowMap != null) { - backingRowMap.clear(); - } - maintainEmptyInvariant(); - } - - @Override - protected Set> createEntrySet() { - return new RowEntrySet(); - } - - private final class RowEntrySet extends Maps.EntrySet { - @Override - Map map() { - return Row.this; - } - - @Override - public int size() { - Map map = backingRowMap(); - return (map == null) ? 0 : map.size(); - } - - @Override - public Iterator> iterator() { - final Map map = backingRowMap(); - if (map == null) { - return Iterators.emptyModifiableIterator(); - } - final Iterator> iterator = map.entrySet().iterator(); - return new Iterator>() { - @Override public boolean hasNext() { - return iterator.hasNext(); - } - @Override public Entry next() { - final Entry entry = iterator.next(); - return new ForwardingMapEntry() { - @Override protected Entry delegate() { - return entry; - } - @Override public V setValue(V value) { - return super.setValue(checkNotNull(value)); - } - @Override - public boolean equals(Object object) { - // TODO(user): identify why this affects GWT tests - return standardEquals(object); - } - }; - } - - @Override - public void remove() { - iterator.remove(); - maintainEmptyInvariant(); - } - }; - } - } - } - - /** - * {@inheritDoc} - * - *

The returned map's views have iterators that don't support - * {@code remove()}. - */ - @Override public Map column(C columnKey) { - return new Column(columnKey); - } - - private class Column extends ImprovedAbstractMap { - final C columnKey; - - Column(C columnKey) { - this.columnKey = checkNotNull(columnKey); - } - - @Override public V put(R key, V value) { - return StandardTable.this.put(key, columnKey, value); - } - - @Override public V get(Object key) { - return StandardTable.this.get(key, columnKey); - } - - @Override public boolean containsKey(Object key) { - return StandardTable.this.contains(key, columnKey); - } - - @Override public V remove(Object key) { - return StandardTable.this.remove(key, columnKey); - } - - /** - * Removes all {@code Column} mappings whose row key and value satisfy the - * given predicate. - */ - boolean removeFromColumnIf(Predicate> predicate) { - boolean changed = false; - Iterator>> iterator - = backingMap.entrySet().iterator(); - while (iterator.hasNext()) { - Entry> entry = iterator.next(); - Map map = entry.getValue(); - V value = map.get(columnKey); - if (value != null - && predicate.test(Maps.immutableEntry(entry.getKey(), value))) { - map.remove(columnKey); - changed = true; - if (map.isEmpty()) { - iterator.remove(); - } - } - } - return changed; - } - - @Override Set> createEntrySet() { - return new EntrySet(); - } - - private class EntrySet extends ImprovedAbstractSet> { - @Override public Iterator> iterator() { - return new EntrySetIterator(); - } - - @Override public int size() { - int size = 0; - for (Map map : backingMap.values()) { - if (map.containsKey(columnKey)) { - size++; - } - } - return size; - } - - @Override public boolean isEmpty() { - return !containsColumn(columnKey); - } - - @Override public void clear() { - removeFromColumnIf(alwaysTrue()); - } - - @Override public boolean contains(Object o) { - if (o instanceof Entry) { - Entry entry = (Entry) o; - return containsMapping(entry.getKey(), columnKey, entry.getValue()); - } - return false; - } - - @Override public boolean remove(Object obj) { - if (obj instanceof Entry) { - Entry entry = (Entry) obj; - return removeMapping(entry.getKey(), columnKey, entry.getValue()); - } - return false; - } - - @Override public boolean retainAll(Collection c) { - return removeFromColumnIf(not(in(c))); - } - } - - private class EntrySetIterator extends AbstractIterator> { - final Iterator>> iterator - = backingMap.entrySet().iterator(); - @Override protected Entry computeNext() { - while (iterator.hasNext()) { - final Entry> entry = iterator.next(); - if (entry.getValue().containsKey(columnKey)) { - return new AbstractMapEntry() { - @Override public R getKey() { - return entry.getKey(); - } - @Override public V getValue() { - return entry.getValue().get(columnKey); - } - @Override public V setValue(V value) { - return entry.getValue().put(columnKey, checkNotNull(value)); - } - }; - } - } - return endOfData(); - } - } - - @Override Set createKeySet() { - return new KeySet(); - } - - private class KeySet extends Maps.KeySet { - KeySet() { - super(Column.this); - } - - @Override public boolean contains(Object obj) { - return StandardTable.this.contains(obj, columnKey); - } - - @Override public boolean remove(Object obj) { - return StandardTable.this.remove(obj, columnKey) != null; - } - - @Override public boolean retainAll(final Collection c) { - return removeFromColumnIf(Maps.keyPredicateOnEntries(not(in(c)))); - } - } - - @Override - Collection createValues() { - return new Values(); - } - - private class Values extends Maps.Values { - Values() { - super(Column.this); - } - - @Override public boolean remove(Object obj) { - return obj != null && removeFromColumnIf(Maps.valuePredicateOnEntries(equalTo(obj))); - } - - @Override public boolean removeAll(final Collection c) { - return removeFromColumnIf(Maps.valuePredicateOnEntries(in(c))); - } - - @Override public boolean retainAll(final Collection c) { - return removeFromColumnIf(Maps.valuePredicateOnEntries(not(in(c)))); - } - } - } - - @Override public Set rowKeySet() { - return rowMap().keySet(); - } - - private transient Set columnKeySet; - - /** - * {@inheritDoc} - * - *

The returned set has an iterator that does not support {@code remove()}. - * - *

The set's iterator traverses the columns of the first row, the - * columns of the second row, etc., skipping any columns that have - * appeared previously. - */ - @Override - public Set columnKeySet() { - Set result = columnKeySet; - return (result == null) ? columnKeySet = new ColumnKeySet() : result; - } - - private class ColumnKeySet extends TableSet { - @Override public Iterator iterator() { - return createColumnKeyIterator(); - } - - @Override public int size() { - return Iterators.size(iterator()); - } - - @Override public boolean remove(Object obj) { - if (obj == null) { - return false; - } - boolean changed = false; - Iterator> iterator = backingMap.values().iterator(); - while (iterator.hasNext()) { - Map map = iterator.next(); - if (map.keySet().remove(obj)) { - changed = true; - if (map.isEmpty()) { - iterator.remove(); - } - } - } - return changed; - } - - @Override public boolean removeAll(Collection c) { - checkNotNull(c); - boolean changed = false; - Iterator> iterator = backingMap.values().iterator(); - while (iterator.hasNext()) { - Map map = iterator.next(); - // map.keySet().removeAll(c) can throw a NPE when map is a TreeMap with - // natural ordering and c contains a null. - if (Iterators.removeAll(map.keySet().iterator(), c)) { - changed = true; - if (map.isEmpty()) { - iterator.remove(); - } - } - } - return changed; - } - - @Override public boolean retainAll(Collection c) { - checkNotNull(c); - boolean changed = false; - Iterator> iterator = backingMap.values().iterator(); - while (iterator.hasNext()) { - Map map = iterator.next(); - if (map.keySet().retainAll(c)) { - changed = true; - if (map.isEmpty()) { - iterator.remove(); - } - } - } - return changed; - } - - @Override public boolean contains(Object obj) { - return containsColumn(obj); - } - } - - /** - * Creates an iterator that returns each column value with duplicates - * omitted. - */ - Iterator createColumnKeyIterator() { - return new ColumnKeyIterator(); - } - - private class ColumnKeyIterator extends AbstractIterator { - // Use the same map type to support TreeMaps with comparators that aren't - // consistent with equals(). - final Map seen = Maps.newHashMapWithExpectedSize(0); - final Iterator> mapIterator = backingMap.values().iterator(); - Iterator> entryIterator = Iterators.emptyIterator(); - - @Override protected C computeNext() { - while (true) { - if (entryIterator.hasNext()) { - Entry entry = entryIterator.next(); - if (!seen.containsKey(entry.getKey())) { - seen.put(entry.getKey(), entry.getValue()); - return entry.getKey(); - } - } else if (mapIterator.hasNext()) { - entryIterator = mapIterator.next().entrySet().iterator(); - } else { - return endOfData(); - } - } - } - } - - /** - * {@inheritDoc} - * - *

The collection's iterator traverses the values for the first row, - * the values for the second row, and so on. - */ - @Override public Collection values() { - return super.values(); - } - - private transient Map> rowMap; - - @Override public Map> rowMap() { - Map> result = rowMap; - return (result == null) ? rowMap = createRowMap() : result; - } - - Map> createRowMap() { - return new RowMap(); - } - - class RowMap extends ImprovedAbstractMap> { - @Override public boolean containsKey(Object key) { - return containsRow(key); - } - - // performing cast only when key is in backing map and has the correct type - - @Override public Map get(Object key) { - return containsRow(key) ? row((R) key) : null; - } - - @Override public Map remove(Object key) { - return (key == null) ? null : backingMap.remove(key); - } - - @Override protected Set>> createEntrySet() { - return new EntrySet(); - } - - class EntrySet extends TableSet>> { - @Override public Iterator>> iterator() { - return Maps.asMapEntryIterator(backingMap.keySet(), new Function>() { - @Override - public Map apply(R rowKey) { - return row(rowKey); - } - }); - } - - @Override public int size() { - return backingMap.size(); - } - - @Override public boolean contains(Object obj) { - if (obj instanceof Entry) { - Entry entry = (Entry) obj; - return entry.getKey() != null - && entry.getValue() instanceof Map - && Filter.safeContains(backingMap.entrySet(), entry); - } - return false; - } - - @Override public boolean remove(Object obj) { - if (obj instanceof Entry) { - Entry entry = (Entry) obj; - return entry.getKey() != null - && entry.getValue() instanceof Map - && backingMap.entrySet().remove(entry); - } - return false; - } - } - } - - private transient ColumnMap columnMap; - - @Override public Map> columnMap() { - ColumnMap result = columnMap; - return (result == null) ? columnMap = new ColumnMap() : result; - } - - private class ColumnMap extends ImprovedAbstractMap> { - // The cast to C occurs only when the key is in the map, implying that it - // has the correct type. - - @Override public Map get(Object key) { - return containsColumn(key) ? column((C) key) : null; - } - - @Override public boolean containsKey(Object key) { - return containsColumn(key); - } - - @Override public Map remove(Object key) { - return containsColumn(key) ? removeColumn(key) : null; - } - - @Override public Set>> createEntrySet() { - return new ColumnMapEntrySet(); - } - - @Override public Set keySet() { - return columnKeySet(); - } - - @Override Collection> createValues() { - return new ColumnMapValues(); - } - - class ColumnMapEntrySet extends TableSet>> { - @Override public Iterator>> iterator() { - return Maps.asMapEntryIterator(columnKeySet(), new Function>() { - @Override - public Map apply(C columnKey) { - return column(columnKey); - } - }); - } - - @Override public int size() { - return columnKeySet().size(); - } - - @Override public boolean contains(Object obj) { - if (obj instanceof Entry) { - Entry entry = (Entry) obj; - if (containsColumn(entry.getKey())) { - // The cast to C occurs only when the key is in the map, implying - // that it has the correct type. - - C columnKey = (C) entry.getKey(); - return get(columnKey).equals(entry.getValue()); - } - } - return false; - } - - @Override public boolean remove(Object obj) { - if (contains(obj)) { - Entry entry = (Entry) obj; - removeColumn(entry.getKey()); - return true; - } - return false; - } - - @Override public boolean removeAll(Collection c) { - /* - * We can't inherit the normal implementation (which calls - * Sets.removeAllImpl(Set, *Collection*) because, under some - * circumstances, it attempts to call columnKeySet().iterator().remove, - * which is unsupported. - */ - checkNotNull(c); - return Sets.removeAllImpl(this, c.iterator()); - } - - @Override public boolean retainAll(Collection c) { - checkNotNull(c); - boolean changed = false; - for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) { - if (!c.contains(Maps.immutableEntry(columnKey, column(columnKey)))) { - removeColumn(columnKey); - changed = true; - } - } - return changed; - } - } - - private class ColumnMapValues extends Maps.Values> { - ColumnMapValues() { - super(ColumnMap.this); - } - - @Override public boolean remove(Object obj) { - for (Entry> entry : ColumnMap.this.entrySet()) { - if (entry.getValue().equals(obj)) { - removeColumn(entry.getKey()); - return true; - } - } - return false; - } - - @Override public boolean removeAll(Collection c) { - checkNotNull(c); - boolean changed = false; - for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) { - if (c.contains(column(columnKey))) { - removeColumn(columnKey); - changed = true; - } - } - return changed; - } - - @Override public boolean retainAll(Collection c) { - checkNotNull(c); - boolean changed = false; - for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) { - if (!c.contains(column(columnKey))) { - removeColumn(columnKey); - changed = true; - } - } - return changed; - } - } - } - - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/collect/Table.java b/java/src/game/collect/Table.java deleted file mode 100644 index 7ed64a2..0000000 --- a/java/src/game/collect/Table.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -/** - * A collection that associates an ordered pair of keys, called a row key and a - * column key, with a single value. A table may be sparse, with only a small - * fraction of row key / column key pairs possessing a corresponding value. - * - *

The mappings corresponding to a given row key may be viewed as a {@link - * Map} whose keys are the columns. The reverse is also available, associating a - * column with a row key / value map. Note that, in some implementations, data - * access by column key may have fewer supported operations or worse performance - * than data access by row key. - * - *

The methods returning collections or maps always return views of the - * underlying table. Updating the table can change the contents of those - * collections, and updating the collections will change the table. - * - *

All methods that modify the table are optional, and the views returned by - * the table may or may not be modifiable. When modification isn't supported, - * those methods will throw an {@link UnsupportedOperationException}. - * - *

See the Guava User Guide article on - * {@code Table}. - * - * @author Jared Levy - * @param the type of the table row keys - * @param the type of the table column keys - * @param the type of the mapped values - * @since 7.0 - */ - -public interface Table { - // TODO(jlevy): Consider adding methods similar to ConcurrentMap methods. - - // Accessors - - /** - * Returns {@code true} if the table contains a mapping with the specified - * row and column keys. - * - * @param rowKey key of row to search for - * @param columnKey key of column to search for - */ - boolean contains(Object rowKey, Object columnKey); - - /** - * Returns {@code true} if the table contains a mapping with the specified - * row key. - * - * @param rowKey key of row to search for - */ - boolean containsRow(Object rowKey); - - /** - * Returns {@code true} if the table contains a mapping with the specified - * column. - * - * @param columnKey key of column to search for - */ - boolean containsColumn(Object columnKey); - - /** - * Returns {@code true} if the table contains a mapping with the specified - * value. - * - * @param value value to search for - */ - boolean containsValue(Object value); - - /** - * Returns the value corresponding to the given row and column keys, or - * {@code null} if no such mapping exists. - * - * @param rowKey key of row to search for - * @param columnKey key of column to search for - */ - V get(Object rowKey, Object columnKey); - - /** Returns {@code true} if the table contains no mappings. */ - boolean isEmpty(); - - /** - * Returns the number of row key / column key / value mappings in the table. - */ - int size(); - - /** - * Compares the specified object with this table for equality. Two tables are - * equal when their cell views, as returned by {@link #cellSet}, are equal. - */ - @Override - boolean equals(Object obj); - - /** - * Returns the hash code for this table. The hash code of a table is defined - * as the hash code of its cell view, as returned by {@link #cellSet}. - */ - @Override - int hashCode(); - - // Mutators - - /** Removes all mappings from the table. */ - void clear(); - - /** - * Associates the specified value with the specified keys. If the table - * already contained a mapping for those keys, the old value is replaced with - * the specified value. - * - * @param rowKey row key that the value should be associated with - * @param columnKey column key that the value should be associated with - * @param value value to be associated with the specified keys - * @return the value previously associated with the keys, or {@code null} if - * no mapping existed for the keys - */ - V put(R rowKey, C columnKey, V value); - - /** - * Copies all mappings from the specified table to this table. The effect is - * equivalent to calling {@link #put} with each row key / column key / value - * mapping in {@code table}. - * - * @param table the table to add to this table - */ - void putAll(Table table); - - /** - * Removes the mapping, if any, associated with the given keys. - * - * @param rowKey row key of mapping to be removed - * @param columnKey column key of mapping to be removed - * @return the value previously associated with the keys, or {@code null} if - * no such value existed - */ - V remove(Object rowKey, Object columnKey); - - // Views - - /** - * Returns a view of all mappings that have the given row key. For each row - * key / column key / value mapping in the table with that row key, the - * returned map associates the column key with the value. If no mappings in - * the table have the provided row key, an empty map is returned. - * - *

Changes to the returned map will update the underlying table, and vice - * versa. - * - * @param rowKey key of row to search for in the table - * @return the corresponding map from column keys to values - */ - Map row(R rowKey); - - /** - * Returns a view of all mappings that have the given column key. For each row - * key / column key / value mapping in the table with that column key, the - * returned map associates the row key with the value. If no mappings in the - * table have the provided column key, an empty map is returned. - * - *

Changes to the returned map will update the underlying table, and vice - * versa. - * - * @param columnKey key of column to search for in the table - * @return the corresponding map from row keys to values - */ - Map column(C columnKey); - - /** - * Returns a set of all row key / column key / value triplets. Changes to the - * returned set will update the underlying table, and vice versa. The cell set - * does not support the {@code add} or {@code addAll} methods. - * - * @return set of table cells consisting of row key / column key / value - * triplets - */ - Set> cellSet(); - - /** - * Returns a set of row keys that have one or more values in the table. - * Changes to the set will update the underlying table, and vice versa. - * - * @return set of row keys - */ - Set rowKeySet(); - - /** - * Returns a set of column keys that have one or more values in the table. - * Changes to the set will update the underlying table, and vice versa. - * - * @return set of column keys - */ - Set columnKeySet(); - - /** - * Returns a collection of all values, which may contain duplicates. Changes - * to the returned collection will update the underlying table, and vice - * versa. - * - * @return collection of values - */ - Collection values(); - - /** - * Returns a view that associates each row key with the corresponding map from - * column keys to values. Changes to the returned map will update this table. - * The returned map does not support {@code put()} or {@code putAll()}, or - * {@code setValue()} on its entries. - * - *

In contrast, the maps returned by {@code rowMap().get()} have the same - * behavior as those returned by {@link #row}. Those maps may support {@code - * setValue()}, {@code put()}, and {@code putAll()}. - * - * @return a map view from each row key to a secondary map from column keys to - * values - */ - Map> rowMap(); - - /** - * Returns a view that associates each column key with the corresponding map - * from row keys to values. Changes to the returned map will update this - * table. The returned map does not support {@code put()} or {@code putAll()}, - * or {@code setValue()} on its entries. - * - *

In contrast, the maps returned by {@code columnMap().get()} have the - * same behavior as those returned by {@link #column}. Those maps may support - * {@code setValue()}, {@code put()}, and {@code putAll()}. - * - * @return a map view from each column key to a secondary map from row keys to - * values - */ - Map> columnMap(); - - /** - * Row key / column key / value triplet corresponding to a mapping in a table. - * - * @since 7.0 - */ - interface Cell { - /** - * Returns the row key of this cell. - */ - R getRowKey(); - - /** - * Returns the column key of this cell. - */ - C getColumnKey(); - - /** - * Returns the value of this cell. - */ - V getValue(); - - /** - * Compares the specified object with this cell for equality. Two cells are - * equal when they have equal row keys, column keys, and values. - */ - @Override - boolean equals(Object obj); - - /** - * Returns the hash code of this cell. - * - *

The hash code of a table cell is equal to {@link - * Objects#hashCode}{@code (e.getRowKey(), e.getColumnKey(), e.getValue())}. - */ - @Override - int hashCode(); - } -} diff --git a/java/src/game/collect/TransformedIterator.java b/java/src/game/collect/TransformedIterator.java deleted file mode 100644 index 1c12f07..0000000 --- a/java/src/game/collect/TransformedIterator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import static game.collect.Preconditions.checkNotNull; - -import java.util.Iterator; - -/** - * An iterator that transforms a backing iterator; for internal use. This avoids - * the object overhead of constructing a {@link Function} for internal methods. - * - * @author Louis Wasserman - */ - -abstract class TransformedIterator implements Iterator { - final Iterator backingIterator; - - TransformedIterator(Iterator backingIterator) { - this.backingIterator = checkNotNull(backingIterator); - } - - abstract T transform(F from); - - @Override - public final boolean hasNext() { - return backingIterator.hasNext(); - } - - @Override - public final T next() { - return transform(backingIterator.next()); - } - - @Override - public final void remove() { - backingIterator.remove(); - } -} diff --git a/java/src/game/collect/UnmodifiableIterator.java b/java/src/game/collect/UnmodifiableIterator.java deleted file mode 100644 index 95024eb..0000000 --- a/java/src/game/collect/UnmodifiableIterator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.Iterator; - -/** - * An iterator that does not support {@link #remove}. - * - * @author Jared Levy - * @since 2.0 (imported from Google Collections Library) - */ - -public abstract class UnmodifiableIterator implements Iterator { - /** Constructor for use by subclasses. */ - protected UnmodifiableIterator() {} - - /** - * Guaranteed to throw an exception and leave the underlying data unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated - @Override - public final void remove() { - throw new UnsupportedOperationException(); - } -} diff --git a/java/src/game/collect/UnmodifiableListIterator.java b/java/src/game/collect/UnmodifiableListIterator.java deleted file mode 100644 index 1a62751..0000000 --- a/java/src/game/collect/UnmodifiableListIterator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.collect; - -import java.util.ListIterator; - -/** - * A list iterator that does not support {@link #remove}, {@link #add}, or - * {@link #set}. - * - * @since 7.0 - * @author Louis Wasserman - */ - -abstract class UnmodifiableListIterator - extends UnmodifiableIterator implements ListIterator { - /** Constructor for use by subclasses. */ - protected UnmodifiableListIterator() {} - - /** - * Guaranteed to throw an exception and leave the underlying data unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated @Override public final void add(E e) { - throw new UnsupportedOperationException(); - } - - /** - * Guaranteed to throw an exception and leave the underlying data unmodified. - * - * @throws UnsupportedOperationException always - * @deprecated Unsupported operation. - */ - @Deprecated @Override public final void set(E e) { - throw new UnsupportedOperationException(); - } -} diff --git a/java/src/game/color/DyeColor.java b/java/src/game/color/DyeColor.java index 15e7550..b53aec1 100755 --- a/java/src/game/color/DyeColor.java +++ b/java/src/game/color/DyeColor.java @@ -2,7 +2,8 @@ package game.color; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.properties.IStringSerializable; public enum DyeColor implements IStringSerializable diff --git a/java/src/game/command/ArgumentParser.java b/java/src/game/command/ArgumentParser.java index d4c6f4e..b1f0ab3 100644 --- a/java/src/game/command/ArgumentParser.java +++ b/java/src/game/command/ArgumentParser.java @@ -2,7 +2,7 @@ package game.command; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; public abstract class ArgumentParser { public static String[][] splitString(String str) { diff --git a/java/src/game/command/CachedExecutable.java b/java/src/game/command/CachedExecutable.java index 0668d50..424c5e4 100644 --- a/java/src/game/command/CachedExecutable.java +++ b/java/src/game/command/CachedExecutable.java @@ -3,8 +3,8 @@ package game.command; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; public class CachedExecutable { private final Executable executable; diff --git a/java/src/game/command/EnumParser.java b/java/src/game/command/EnumParser.java index 83028f2..9982316 100644 --- a/java/src/game/command/EnumParser.java +++ b/java/src/game/command/EnumParser.java @@ -2,7 +2,7 @@ package game.command; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; public class EnumParser extends DefaultingParser { private final Map lookup = Maps.newHashMap(); diff --git a/java/src/game/command/ScriptArgs.java b/java/src/game/command/ScriptArgs.java index daab091..d792cdc 100644 --- a/java/src/game/command/ScriptArgs.java +++ b/java/src/game/command/ScriptArgs.java @@ -3,8 +3,9 @@ package game.command; import java.util.List; import java.util.Map; +import com.google.common.collect.Maps; + import game.block.Block; -import game.collect.Maps; import game.entity.Entity; import game.entity.npc.EntityNPC; import game.entity.types.EntityLiving; diff --git a/java/src/game/command/ScriptEnvironment.java b/java/src/game/command/ScriptEnvironment.java index 5ab3093..399db08 100644 --- a/java/src/game/command/ScriptEnvironment.java +++ b/java/src/game/command/ScriptEnvironment.java @@ -4,9 +4,10 @@ import java.util.List; import java.util.Map; import java.util.function.Function; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.Server; -import game.collect.Lists; -import game.collect.Maps; import game.color.TextColor; public class ScriptEnvironment { diff --git a/java/src/game/command/ScriptExecutable.java b/java/src/game/command/ScriptExecutable.java index 9cbf605..858ac7c 100644 --- a/java/src/game/command/ScriptExecutable.java +++ b/java/src/game/command/ScriptExecutable.java @@ -2,8 +2,8 @@ package game.command; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; public abstract class ScriptExecutable implements Executable { private final String name; diff --git a/java/src/game/command/StringParser.java b/java/src/game/command/StringParser.java index 6eb7187..4d5d5be 100644 --- a/java/src/game/command/StringParser.java +++ b/java/src/game/command/StringParser.java @@ -1,6 +1,6 @@ package game.command; -import java.util.function.Predicate; +import com.google.common.base.Predicate; public class StringParser extends DefaultingParser { private final boolean allowEmpty; diff --git a/java/src/game/command/WorldParser.java b/java/src/game/command/WorldParser.java index 9c9a40a..d43b574 100644 --- a/java/src/game/command/WorldParser.java +++ b/java/src/game/command/WorldParser.java @@ -2,8 +2,9 @@ package game.command; import java.util.List; +import com.google.common.collect.Lists; + import game.Server; -import game.collect.Lists; import game.dimension.Dimension; import game.world.WorldServer; diff --git a/java/src/game/dimension/DimType.java b/java/src/game/dimension/DimType.java index e2fa8e4..8bc412f 100755 --- a/java/src/game/dimension/DimType.java +++ b/java/src/game/dimension/DimType.java @@ -2,7 +2,7 @@ package game.dimension; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; public enum DimType { STAR("star", "Stern %s", true, false, false, false, false, false, true), diff --git a/java/src/game/dimension/Dimension.java b/java/src/game/dimension/Dimension.java index 7c330a9..2648754 100755 --- a/java/src/game/dimension/Dimension.java +++ b/java/src/game/dimension/Dimension.java @@ -4,11 +4,12 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import game.biome.Biome; import game.block.LeavesType; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; import game.init.BlockRegistry; import game.init.Blocks; import game.init.MetalType; diff --git a/java/src/game/dimension/Domain.java b/java/src/game/dimension/Domain.java index 91e640c..038a1fe 100755 --- a/java/src/game/dimension/Domain.java +++ b/java/src/game/dimension/Domain.java @@ -2,7 +2,7 @@ package game.dimension; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; public final class Domain extends Nameable implements Comparable { public final String id; diff --git a/java/src/game/dimension/Galaxy.java b/java/src/game/dimension/Galaxy.java index fa44e2f..30bb6b8 100755 --- a/java/src/game/dimension/Galaxy.java +++ b/java/src/game/dimension/Galaxy.java @@ -2,7 +2,7 @@ package game.dimension; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; public final class Galaxy extends Nameable implements Comparable { public final String id; diff --git a/java/src/game/dimension/Planet.java b/java/src/game/dimension/Planet.java index 19689b7..9c23687 100755 --- a/java/src/game/dimension/Planet.java +++ b/java/src/game/dimension/Planet.java @@ -2,7 +2,7 @@ package game.dimension; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; public final class Planet extends Dimension { private final Set moons = Sets.newTreeSet(); diff --git a/java/src/game/dimension/Sector.java b/java/src/game/dimension/Sector.java index 4d11d4e..440105c 100755 --- a/java/src/game/dimension/Sector.java +++ b/java/src/game/dimension/Sector.java @@ -2,7 +2,7 @@ package game.dimension; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; public final class Sector extends Nameable implements Comparable { public final String id; diff --git a/java/src/game/dimension/Star.java b/java/src/game/dimension/Star.java index 4a2452b..8bce018 100755 --- a/java/src/game/dimension/Star.java +++ b/java/src/game/dimension/Star.java @@ -2,7 +2,8 @@ package game.dimension; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; + import game.world.State; public final class Star extends Dimension { diff --git a/java/src/game/enchantment/Enchantment.java b/java/src/game/enchantment/Enchantment.java index 2241101..e981617 100755 --- a/java/src/game/enchantment/Enchantment.java +++ b/java/src/game/enchantment/Enchantment.java @@ -4,8 +4,9 @@ import java.util.List; import java.util.Map; import java.util.Set; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.entity.DamageSource; import game.entity.Entity; import game.entity.types.EntityLiving; diff --git a/java/src/game/enchantment/EnchantmentHelper.java b/java/src/game/enchantment/EnchantmentHelper.java index c0ed87d..25d6fa9 100755 --- a/java/src/game/enchantment/EnchantmentHelper.java +++ b/java/src/game/enchantment/EnchantmentHelper.java @@ -4,8 +4,9 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.entity.DamageSource; import game.entity.Entity; import game.entity.types.EntityLiving; diff --git a/java/src/game/entity/DataWatcher.java b/java/src/game/entity/DataWatcher.java index bc7f2a7..6c13746 100755 --- a/java/src/game/entity/DataWatcher.java +++ b/java/src/game/entity/DataWatcher.java @@ -6,8 +6,9 @@ import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.item.ItemStack; import game.network.PacketBuffer; import game.world.BlockPos; diff --git a/java/src/game/entity/EntityTrackerEntry.java b/java/src/game/entity/EntityTrackerEntry.java index b7b1903..c34fd71 100755 --- a/java/src/game/entity/EntityTrackerEntry.java +++ b/java/src/game/entity/EntityTrackerEntry.java @@ -4,7 +4,8 @@ import java.util.Collection; import java.util.List; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; + import game.entity.attributes.AttributeInstance; import game.entity.attributes.AttributeMap; import game.entity.npc.EntityNPC; diff --git a/java/src/game/entity/animal/EntityDragon.java b/java/src/game/entity/animal/EntityDragon.java index 1f4e692..178b69a 100755 --- a/java/src/game/entity/animal/EntityDragon.java +++ b/java/src/game/entity/animal/EntityDragon.java @@ -2,7 +2,8 @@ package game.entity.animal; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.DamageSource; import game.entity.Entity; import game.entity.npc.Alignment; diff --git a/java/src/game/entity/animal/EntityHorse.java b/java/src/game/entity/animal/EntityHorse.java index e48905a..5504239 100755 --- a/java/src/game/entity/animal/EntityHorse.java +++ b/java/src/game/entity/animal/EntityHorse.java @@ -1,6 +1,6 @@ package game.entity.animal; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.ai.EntityAIFollowParent; import game.ai.EntityAILookIdle; @@ -44,7 +44,7 @@ public class EntityHorse extends EntityAnimal implements IInvBasic { private static final Predicate horseBreedingSelector = new Predicate() { - public boolean test(Entity p_apply_1_) + public boolean apply(Entity p_apply_1_) { return p_apply_1_ instanceof EntityHorse && ((EntityHorse)p_apply_1_).isBreeding(); } diff --git a/java/src/game/entity/animal/EntityOcelot.java b/java/src/game/entity/animal/EntityOcelot.java index 81c2736..da1b07f 100755 --- a/java/src/game/entity/animal/EntityOcelot.java +++ b/java/src/game/entity/animal/EntityOcelot.java @@ -1,6 +1,6 @@ package game.entity.animal; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.ai.EntityAIAvoidEntity; import game.ai.EntityAIFollowOwner; @@ -56,7 +56,7 @@ public class EntityOcelot extends EntityTameable this.tasks.addTask(10, new EntityAIWander(this, 0.8D)); this.tasks.addTask(11, new EntityAIWatchClosest(this, null, 10.0F)); this.targets.addTask(1, new EntityAITargetNonTamed(this, EntityAnimal.class, false, new Predicate() { - public boolean test(EntityAnimal entity) { + public boolean apply(EntityAnimal entity) { return entity instanceof EntityChicken || entity instanceof EntityMouse; } })); diff --git a/java/src/game/entity/animal/EntityRabbit.java b/java/src/game/entity/animal/EntityRabbit.java index 0aaa080..cc8a054 100755 --- a/java/src/game/entity/animal/EntityRabbit.java +++ b/java/src/game/entity/animal/EntityRabbit.java @@ -1,6 +1,6 @@ package game.entity.animal; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.ai.EntityAIAttackOnCollide; import game.ai.EntityAIAvoidEntity; @@ -336,7 +336,7 @@ public class EntityRabbit extends EntityAnimal { this.grow(this.rand.range(250, 350)); if(Config.rabbitMateChance > 0 && this.rand.chance(Config.rabbitMateChance) && this.getGrowingAge() == 0 && !this.isInLove() && !this.worldObj.getEntitiesWithinAABB(EntityRabbit.class, this.getEntityBoundingBox().expand(15.0f, 15.0f, 15.0f), new Predicate() { - public boolean test(EntityRabbit entity) { + public boolean apply(EntityRabbit entity) { return entity != EntityRabbit.this && entity.getGrowingAge() == 0; } }).isEmpty()) diff --git a/java/src/game/entity/animal/EntitySheep.java b/java/src/game/entity/animal/EntitySheep.java index 97a93da..e42bfa0 100755 --- a/java/src/game/entity/animal/EntitySheep.java +++ b/java/src/game/entity/animal/EntitySheep.java @@ -2,6 +2,8 @@ package game.entity.animal; import java.util.Map; +import com.google.common.collect.Maps; + import game.ai.EntityAIEatGrass; import game.ai.EntityAIFollowParent; import game.ai.EntityAILookIdle; @@ -12,7 +14,6 @@ import game.ai.EntityAITempt; import game.ai.EntityAIWander; import game.ai.EntityAIWatchClosest; import game.biome.Biome; -import game.collect.Maps; import game.color.DyeColor; import game.entity.attributes.Attributes; import game.entity.item.EntityItem; diff --git a/java/src/game/entity/animal/EntityWolf.java b/java/src/game/entity/animal/EntityWolf.java index d58182b..ce77c99 100755 --- a/java/src/game/entity/animal/EntityWolf.java +++ b/java/src/game/entity/animal/EntityWolf.java @@ -1,6 +1,6 @@ package game.entity.animal; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.ai.EntityAIAttackOnCollide; import game.ai.EntityAIBeg; @@ -74,7 +74,7 @@ public class EntityWolf extends EntityTameable this.targets.addTask(3, new EntityAIHurtByTarget(this, true)); this.targets.addTask(4, new EntityAITargetNonTamed(this, EntityAnimal.class, false, new Predicate() { - public boolean test(Entity p_apply_1_) + public boolean apply(Entity p_apply_1_) { return p_apply_1_ instanceof EntitySheep || p_apply_1_ instanceof EntityRabbit; } diff --git a/java/src/game/entity/attributes/Attribute.java b/java/src/game/entity/attributes/Attribute.java index 81ea3b4..e1987e9 100755 --- a/java/src/game/entity/attributes/Attribute.java +++ b/java/src/game/entity/attributes/Attribute.java @@ -2,7 +2,8 @@ package game.entity.attributes; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.util.ExtMath; public class Attribute diff --git a/java/src/game/entity/attributes/AttributeInstance.java b/java/src/game/entity/attributes/AttributeInstance.java index c4db291..7b29c4c 100755 --- a/java/src/game/entity/attributes/AttributeInstance.java +++ b/java/src/game/entity/attributes/AttributeInstance.java @@ -4,9 +4,9 @@ import java.util.Collection; import java.util.Map; import java.util.Set; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; public class AttributeInstance { diff --git a/java/src/game/entity/attributes/AttributeMap.java b/java/src/game/entity/attributes/AttributeMap.java index af5666e..1079671 100755 --- a/java/src/game/entity/attributes/AttributeMap.java +++ b/java/src/game/entity/attributes/AttributeMap.java @@ -3,10 +3,11 @@ package game.entity.attributes; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; -import game.collect.Maps; -import game.collect.Sets; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +import java.util.Set; public class AttributeMap { diff --git a/java/src/game/entity/attributes/LowerStringMap.java b/java/src/game/entity/attributes/LowerStringMap.java index 11110bb..74e5f0e 100755 --- a/java/src/game/entity/attributes/LowerStringMap.java +++ b/java/src/game/entity/attributes/LowerStringMap.java @@ -4,7 +4,7 @@ import java.util.Collection; import java.util.Map; import java.util.Set; -import game.collect.Maps; +import com.google.common.collect.Maps; public class LowerStringMap implements Map { diff --git a/java/src/game/entity/item/EntityFalling.java b/java/src/game/entity/item/EntityFalling.java index 2c5da29..5fc61b2 100755 --- a/java/src/game/entity/item/EntityFalling.java +++ b/java/src/game/entity/item/EntityFalling.java @@ -2,11 +2,12 @@ package game.entity.item; import java.util.List; +import com.google.common.collect.Lists; + import game.block.Block; import game.block.BlockAnvil; import game.block.BlockFalling; import game.block.ITileEntityProvider; -import game.collect.Lists; import game.entity.DamageSource; import game.entity.Entity; import game.entity.types.IObjectData; diff --git a/java/src/game/entity/item/EntityHopperCart.java b/java/src/game/entity/item/EntityHopperCart.java index 0953518..986c3a1 100755 --- a/java/src/game/entity/item/EntityHopperCart.java +++ b/java/src/game/entity/item/EntityHopperCart.java @@ -1,7 +1,7 @@ package game.entity.item; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.entity.DamageSource; import game.entity.npc.EntityNPC; @@ -174,7 +174,7 @@ public class EntityHopperCart extends EntityCartContainer implements IHopper else { List list = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.getEntityBoundingBox().expand(0.25D, 0.0D, 0.25D), new Predicate() { - public boolean test(EntityItem entity) { + public boolean apply(EntityItem entity) { return entity.isEntityAlive(); } }); diff --git a/java/src/game/entity/npc/Alignment.java b/java/src/game/entity/npc/Alignment.java index 8e96033..d2e560d 100755 --- a/java/src/game/entity/npc/Alignment.java +++ b/java/src/game/entity/npc/Alignment.java @@ -2,7 +2,8 @@ package game.entity.npc; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.color.TextColor; public enum Alignment { diff --git a/java/src/game/entity/npc/ClassInfo.java b/java/src/game/entity/npc/ClassInfo.java index 478f8ca..5021300 100755 --- a/java/src/game/entity/npc/ClassInfo.java +++ b/java/src/game/entity/npc/ClassInfo.java @@ -2,7 +2,8 @@ package game.entity.npc; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.item.RngLoot; import game.rng.WeightedList; diff --git a/java/src/game/entity/npc/EntityChaosMarine.java b/java/src/game/entity/npc/EntityChaosMarine.java index dd8ce82..1da0aa8 100755 --- a/java/src/game/entity/npc/EntityChaosMarine.java +++ b/java/src/game/entity/npc/EntityChaosMarine.java @@ -2,7 +2,8 @@ package game.entity.npc; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.attributes.Attributes; import game.init.SpeciesRegistry; import game.properties.IStringSerializable; diff --git a/java/src/game/entity/npc/EntityNPC.java b/java/src/game/entity/npc/EntityNPC.java index e0eabc6..fa09c44 100755 --- a/java/src/game/entity/npc/EntityNPC.java +++ b/java/src/game/entity/npc/EntityNPC.java @@ -2,7 +2,8 @@ package game.entity.npc; import java.lang.reflect.InvocationTargetException; import java.util.List; -import java.util.function.Predicate; + +import com.google.common.base.Predicate; import game.Game; import game.ai.AIRangedAttack; @@ -274,7 +275,7 @@ public abstract class EntityNPC extends EntityLiving // this.tasks.addTask(1, new EntityAIAttackOnCollide(this, EntityLivingBase.class, 0.6D, true, true)); this.tasks.addTask(1, new EntityAINpcMate(this)); this.tasks.addTask(2, new EntityAIAvoidEntity(this, EntityLiving.class, new Predicate() { - public boolean test(EntityLiving entity) { + public boolean apply(EntityLiving entity) { return entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity); } }, 8.0F, 1.1D, 1.1D) { @@ -301,7 +302,7 @@ public abstract class EntityNPC extends EntityLiving // } }); this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityLiving.class, new Predicate() { - public boolean test(EntityLiving entity) { + public boolean apply(EntityLiving entity) { return entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity); } }, 8.0F, 1.1D, 1.1D) { @@ -364,7 +365,7 @@ public abstract class EntityNPC extends EntityLiving } }); this.targets.addTask(2, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, true, false, new Predicate() { - public boolean test(EntityLiving entity) { + public boolean apply(EntityLiving entity) { if(entity != null && entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity)) { EntityNPC.this.setAttackTarget(null); EntityNPC.this.fleeing = true; diff --git a/java/src/game/entity/npc/EntityPrimarch.java b/java/src/game/entity/npc/EntityPrimarch.java index 9c5b671..6800921 100755 --- a/java/src/game/entity/npc/EntityPrimarch.java +++ b/java/src/game/entity/npc/EntityPrimarch.java @@ -2,7 +2,8 @@ package game.entity.npc; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.attributes.Attributes; import game.properties.IStringSerializable; import game.rng.Random; diff --git a/java/src/game/entity/npc/EntitySpaceMarine.java b/java/src/game/entity/npc/EntitySpaceMarine.java index db749af..876b441 100755 --- a/java/src/game/entity/npc/EntitySpaceMarine.java +++ b/java/src/game/entity/npc/EntitySpaceMarine.java @@ -2,7 +2,8 @@ package game.entity.npc; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.attributes.Attributes; import game.init.SpeciesRegistry; import game.properties.IStringSerializable; diff --git a/java/src/game/entity/npc/EntityZombie.java b/java/src/game/entity/npc/EntityZombie.java index d3da1e3..7a64395 100755 --- a/java/src/game/entity/npc/EntityZombie.java +++ b/java/src/game/entity/npc/EntityZombie.java @@ -1,7 +1,7 @@ package game.entity.npc; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.ai.EntityAIMoveThroughVillage; import game.entity.DamageSource; @@ -211,7 +211,7 @@ public class EntityZombie extends EntityNPC if ((double)this.worldObj.rand.floatv() < 0.05D) { List list = this.worldObj.getEntitiesWithinAABB(EntityChicken.class, this.getEntityBoundingBox().expand(5.0D, 3.0D, 5.0D), new Predicate() { - public boolean test(EntityChicken entity) { + public boolean apply(EntityChicken entity) { return entity.isEntityAlive() && entity.passenger == null && entity.vehicle == null; } }); diff --git a/java/src/game/entity/npc/SpeciesInfo.java b/java/src/game/entity/npc/SpeciesInfo.java index 4fa9778..e386880 100755 --- a/java/src/game/entity/npc/SpeciesInfo.java +++ b/java/src/game/entity/npc/SpeciesInfo.java @@ -3,11 +3,12 @@ package game.entity.npc; import java.util.List; import java.util.Map; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.Block; -import game.collect.BiMap; -import game.collect.HashBiMap; -import game.collect.Lists; -import game.collect.Maps; import game.init.SpeciesRegistry; import game.init.SpeciesRegistry.ModelType; import game.item.Item; diff --git a/java/src/game/entity/types/EntityAnimal.java b/java/src/game/entity/types/EntityAnimal.java index 7323eaf..75b8498 100755 --- a/java/src/game/entity/types/EntityAnimal.java +++ b/java/src/game/entity/types/EntityAnimal.java @@ -2,8 +2,9 @@ package game.entity.types; import java.util.Set; +import com.google.common.collect.Sets; + import game.block.Block; -import game.collect.Sets; import game.entity.DamageSource; import game.entity.npc.Alignment; import game.entity.npc.EntityNPC; diff --git a/java/src/game/entity/types/EntityLiving.java b/java/src/game/entity/types/EntityLiving.java index 96d5612..d9dd8b5 100755 --- a/java/src/game/entity/types/EntityLiving.java +++ b/java/src/game/entity/types/EntityLiving.java @@ -4,7 +4,10 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import game.ai.EntityAIBase; import game.ai.EntityAIMoveTowardsRestriction; @@ -15,8 +18,6 @@ import game.ai.EntityMoveHelper; import game.ai.EntitySenses; import game.audio.SoundType; import game.block.Block; -import game.collect.Lists; -import game.collect.Maps; import game.color.TextColor; import game.enchantment.EnchantmentHelper; import game.entity.DamageSource; @@ -2124,7 +2125,7 @@ public abstract class EntityLiving extends Entity { List list = this.worldObj.getEntitiesInAABBexcluding(this, this.getEntityBoundingBox().expand(0.20000000298023224D, 0.0D, 0.20000000298023224D), new Predicate() { - public boolean test(Entity p_apply_1_) + public boolean apply(Entity p_apply_1_) { return p_apply_1_.canBePushed(); } diff --git a/java/src/game/future/AbstractFuture.java b/java/src/game/future/AbstractFuture.java deleted file mode 100644 index e63a476..0000000 --- a/java/src/game/future/AbstractFuture.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.AbstractQueuedSynchronizer; - -/** - * An abstract implementation of the {@link ListenableFuture} interface. This - * class is preferable to {@link java.util.concurrent.FutureTask} for two - * reasons: It implements {@code ListenableFuture}, and it does not implement - * {@code Runnable}. (If you want a {@code Runnable} implementation of {@code - * ListenableFuture}, create a {@link ListenableFutureTask}, or submit your - * tasks to a {@link ListeningExecutorService}.) - * - *

This class implements all methods in {@code ListenableFuture}. - * Subclasses should provide a way to set the result of the computation through - * the protected methods {@link #set(Object)} and - * {@link #setException(Throwable)}. Subclasses may also override {@link - * #interruptTask()}, which will be invoked automatically if a call to {@link - * #cancel(boolean) cancel(true)} succeeds in canceling the future. - * - *

{@code AbstractFuture} uses an {@link AbstractQueuedSynchronizer} to deal - * with concurrency issues and guarantee thread safety. - * - *

The state changing methods all return a boolean indicating success or - * failure in changing the future's state. Valid states are running, - * completed, failed, or cancelled. - * - *

This class uses an {@link ExecutionList} to guarantee that all registered - * listeners will be executed, either when the future finishes or, for listeners - * that are added after the future completes, immediately. - * {@code Runnable}-{@code Executor} pairs are stored in the execution list but - * are not necessarily executed in the order in which they were added. (If a - * listener is added after the Future is complete, it will be executed - * immediately, even if earlier listeners have not been executed. Additionally, - * executors need not guarantee FIFO execution, or different listeners may run - * in different executors.) - * - * @author Sven Mawson - * @since 1.0 - */ -abstract class AbstractFuture implements ListenableFuture { - - /** Synchronization control for AbstractFutures. */ - private final Sync sync = new Sync(); - - // The execution list to hold our executors. - private final ExecutionList executionList = new ExecutionList(); - - /** - * Constructor for use by subclasses. - */ - protected AbstractFuture() {} - - /* - * Improve the documentation of when InterruptedException is thrown. Our - * behavior matches the JDK's, but the JDK's documentation is misleading. - */ - /** - * {@inheritDoc} - * - *

The default {@link AbstractFuture} implementation throws {@code - * InterruptedException} if the current thread is interrupted before or during - * the call, even if the value is already available. - * - * @throws InterruptedException if the current thread was interrupted before - * or during the call (optional but recommended). - * @throws CancellationException {@inheritDoc} - */ - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, - TimeoutException, ExecutionException { - return sync.get(unit.toNanos(timeout)); - } - - /* - * Improve the documentation of when InterruptedException is thrown. Our - * behavior matches the JDK's, but the JDK's documentation is misleading. - */ - /** - * {@inheritDoc} - * - *

The default {@link AbstractFuture} implementation throws {@code - * InterruptedException} if the current thread is interrupted before or during - * the call, even if the value is already available. - * - * @throws InterruptedException if the current thread was interrupted before - * or during the call (optional but recommended). - * @throws CancellationException {@inheritDoc} - */ - @Override - public V get() throws InterruptedException, ExecutionException { - return sync.get(); - } - - @Override - public boolean isDone() { - return sync.isDone(); - } - - @Override - public boolean isCancelled() { - return sync.isCancelled(); - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - if (!sync.cancel(mayInterruptIfRunning)) { - return false; - } - executionList.execute(); - if (mayInterruptIfRunning) { - interruptTask(); - } - return true; - } - - /** - * Subclasses can override this method to implement interruption of the - * future's computation. The method is invoked automatically by a successful - * call to {@link #cancel(boolean) cancel(true)}. - * - *

The default implementation does nothing. - * - * @since 10.0 - */ - protected void interruptTask() { - } - - /** - * Returns true if this future was cancelled with {@code - * mayInterruptIfRunning} set to {@code true}. - * - * @since 14.0 - */ - protected final boolean wasInterrupted() { - return sync.wasInterrupted(); - } - - /** - * {@inheritDoc} - * - * @since 10.0 - */ - @Override - public void addListener(Runnable listener, Executor exec) { - executionList.add(listener, exec); - } - - /** - * Subclasses should invoke this method to set the result of the computation - * to {@code value}. This will set the state of the future to - * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the - * state was successfully changed. - * - * @param value the value that was the result of the task. - * @return true if the state was successfully changed. - */ - protected boolean set(V value) { - boolean result = sync.set(value); - if (result) { - executionList.execute(); - } - return result; - } - - /** - * Subclasses should invoke this method to set the result of the computation - * to an error, {@code throwable}. This will set the state of the future to - * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the - * state was successfully changed. - * - * @param throwable the exception that the task failed with. - * @return true if the state was successfully changed. - */ - protected boolean setException(Throwable throwable) { - boolean result = sync.setException(throwable); - if (result) { - executionList.execute(); - } - return result; - } - - /** - *

Following the contract of {@link AbstractQueuedSynchronizer} we create a - * private subclass to hold the synchronizer. This synchronizer is used to - * implement the blocking and waiting calls as well as to handle state changes - * in a thread-safe manner. The current state of the future is held in the - * Sync state, and the lock is released whenever the state changes to - * {@link #COMPLETED}, {@link #CANCELLED}, or {@link #INTERRUPTED} - * - *

To avoid races between threads doing release and acquire, we transition - * to the final state in two steps. One thread will successfully CAS from - * RUNNING to COMPLETING, that thread will then set the result of the - * computation, and only then transition to COMPLETED, CANCELLED, or - * INTERRUPTED. - * - *

We don't use the integer argument passed between acquire methods so we - * pass around a -1 everywhere. - */ - static final class Sync extends AbstractQueuedSynchronizer { - - private static final long serialVersionUID = 0L; - - /* Valid states. */ - static final int RUNNING = 0; - static final int COMPLETING = 1; - static final int COMPLETED = 2; - static final int CANCELLED = 4; - static final int INTERRUPTED = 8; - - private V value; - private Throwable exception; - - /* - * Acquisition succeeds if the future is done, otherwise it fails. - */ - @Override - protected int tryAcquireShared(int ignored) { - if (isDone()) { - return 1; - } - return -1; - } - - /* - * We always allow a release to go through, this means the state has been - * successfully changed and the result is available. - */ - @Override - protected boolean tryReleaseShared(int finalState) { - setState(finalState); - return true; - } - - /** - * Blocks until the task is complete or the timeout expires. Throws a - * {@link TimeoutException} if the timer expires, otherwise behaves like - * {@link #get()}. - */ - V get(long nanos) throws TimeoutException, CancellationException, - ExecutionException, InterruptedException { - - // Attempt to acquire the shared lock with a timeout. - if (!tryAcquireSharedNanos(-1, nanos)) { - throw new TimeoutException("Timeout waiting for task."); - } - - return getValue(); - } - - /** - * Blocks until {@link #complete(Object, Throwable, int)} has been - * successfully called. Throws a {@link CancellationException} if the task - * was cancelled, or a {@link ExecutionException} if the task completed with - * an error. - */ - V get() throws CancellationException, ExecutionException, - InterruptedException { - - // Acquire the shared lock allowing interruption. - acquireSharedInterruptibly(-1); - return getValue(); - } - - /** - * Implementation of the actual value retrieval. Will return the value - * on success, an exception on failure, a cancellation on cancellation, or - * an illegal state if the synchronizer is in an invalid state. - */ - private V getValue() throws CancellationException, ExecutionException { - int state = getState(); - switch (state) { - case COMPLETED: - if (exception != null) { - throw new ExecutionException(exception); - } else { - return value; - } - - case CANCELLED: - case INTERRUPTED: - throw cancellationExceptionWithCause( - "Task was cancelled.", exception); - - default: - throw new IllegalStateException( - "Error, synchronizer in invalid state: " + state); - } - } - - /** - * Checks if the state is {@link #COMPLETED}, {@link #CANCELLED}, or {@link - * INTERRUPTED}. - */ - boolean isDone() { - return (getState() & (COMPLETED | CANCELLED | INTERRUPTED)) != 0; - } - - /** - * Checks if the state is {@link #CANCELLED} or {@link #INTERRUPTED}. - */ - boolean isCancelled() { - return (getState() & (CANCELLED | INTERRUPTED)) != 0; - } - - /** - * Checks if the state is {@link #INTERRUPTED}. - */ - boolean wasInterrupted() { - return getState() == INTERRUPTED; - } - - /** - * Transition to the COMPLETED state and set the value. - */ - boolean set(V v) { - return complete(v, null, COMPLETED); - } - - /** - * Transition to the COMPLETED state and set the exception. - */ - boolean setException(Throwable t) { - return complete(null, t, COMPLETED); - } - - /** - * Transition to the CANCELLED or INTERRUPTED state. - */ - boolean cancel(boolean interrupt) { - return complete(null, null, interrupt ? INTERRUPTED : CANCELLED); - } - - /** - * Implementation of completing a task. Either {@code v} or {@code t} will - * be set but not both. The {@code finalState} is the state to change to - * from {@link #RUNNING}. If the state is not in the RUNNING state we - * return {@code false} after waiting for the state to be set to a valid - * final state ({@link #COMPLETED}, {@link #CANCELLED}, or {@link - * #INTERRUPTED}). - * - * @param v the value to set as the result of the computation. - * @param t the exception to set as the result of the computation. - * @param finalState the state to transition to. - */ - private boolean complete(V v, Throwable t, - int finalState) { - boolean doCompletion = compareAndSetState(RUNNING, COMPLETING); - if (doCompletion) { - // If this thread successfully transitioned to COMPLETING, set the value - // and exception and then release to the final state. - this.value = v; - // Don't actually construct a CancellationException until necessary. - this.exception = ((finalState & (CANCELLED | INTERRUPTED)) != 0) - ? new CancellationException("Future.cancel() was called.") : t; - releaseShared(finalState); - } else if (getState() == COMPLETING) { - // If some other thread is currently completing the future, block until - // they are done so we can guarantee completion. - acquireShared(-1); - } - return doCompletion; - } - } - - static final CancellationException cancellationExceptionWithCause( - String message, Throwable cause) { - CancellationException exception = new CancellationException(message); - exception.initCause(cause); - return exception; - } -} diff --git a/java/src/game/future/ExecutionError.java b/java/src/game/future/ExecutionError.java deleted file mode 100644 index cf8eae0..0000000 --- a/java/src/game/future/ExecutionError.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2011 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -/** - * {@link Error} variant of {@link java.util.concurrent.ExecutionException}. As - * with {@code ExecutionException}, the error's {@linkplain #getCause() cause} - * comes from a failed task, possibly run in another thread. That cause should - * itself be an {@code Error}; if not, use {@code ExecutionException} or {@link - * UncheckedExecutionException}. This allows the client code to continue to - * distinguish between exceptions and errors, even when they come from other - * threads. - * - * @author Chris Povirk - * @since 10.0 - */ - -class ExecutionError extends Error { - /** - * Creates a new instance with {@code null} as its detail message. - */ - protected ExecutionError() {} - - /** - * Creates a new instance with the given detail message. - */ - protected ExecutionError(String message) { - super(message); - } - - /** - * Creates a new instance with the given detail message and cause. - */ - public ExecutionError(String message, Error cause) { - super(message, cause); - } - - /** - * Creates a new instance with the given cause. - */ - public ExecutionError(Error cause) { - super(cause); - } - - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/future/ExecutionList.java b/java/src/game/future/ExecutionList.java deleted file mode 100644 index 79e86cf..0000000 --- a/java/src/game/future/ExecutionList.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -import java.util.concurrent.Executor; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - *

A list of listeners, each with an associated {@code Executor}, that - * guarantees that every {@code Runnable} that is {@linkplain #add added} will - * be executed after {@link #execute()} is called. Any {@code Runnable} added - * after the call to {@code execute} is still guaranteed to execute. There is no - * guarantee, however, that listeners will be executed in the order that they - * are added. - * - *

Exceptions thrown by a listener will be propagated up to the executor. - * Any exception thrown during {@code Executor.execute} (e.g., a {@code - * RejectedExecutionException} or an exception thrown by {@linkplain - * MoreExecutors#sameThreadExecutor inline execution}) will be caught and - * logged. - * - * @author Nishant Thakkar - * @author Sven Mawson - * @since 1.0 - */ -final class ExecutionList { - // Logger to log exceptions caught when running runnables. -// @VisibleForTesting - static final Logger log = Logger.getLogger(ExecutionList.class.getName()); - - /** - * The runnable, executor pairs to execute. This acts as a stack threaded through the - * {@link RunnableExecutorPair#next} field. - */ -// @GuardedBy("this") - private RunnableExecutorPair runnables; -// @GuardedBy("this") - private boolean executed; - - /** Creates a new, empty {@link ExecutionList}. */ - public ExecutionList() {} - - /** - * Adds the {@code Runnable} and accompanying {@code Executor} to the list of - * listeners to execute. If execution has already begun, the listener is - * executed immediately. - * - *

Note: For fast, lightweight listeners that would be safe to execute in - * any thread, consider {@link MoreExecutors#sameThreadExecutor}. For heavier - * listeners, {@code sameThreadExecutor()} carries some caveats: First, the - * thread that the listener runs in depends on whether the {@code - * ExecutionList} has been executed at the time it is added. In particular, - * listeners may run in the thread that calls {@code add}. Second, the thread - * that calls {@link #execute} may be an internal implementation thread, such - * as an RPC network thread, and {@code sameThreadExecutor()} listeners may - * run in this thread. Finally, during the execution of a {@code - * sameThreadExecutor} listener, all other registered but unexecuted - * listeners are prevented from running, even if those listeners are to run - * in other executors. - */ - public void add(Runnable runnable, Executor executor) { - // Fail fast on a null. We throw NPE here because the contract of - // Executor states that it throws NPE on null listener, so we propagate - // that contract up into the add method as well. - - // Lock while we check state. We must maintain the lock while adding the - // new pair so that another thread can't run the list out from under us. - // We only add to the list if we have not yet started execution. - synchronized (this) { - if (!executed) { - runnables = new RunnableExecutorPair(runnable, executor, runnables); - return; - } - } - // Execute the runnable immediately. Because of scheduling this may end up - // getting called before some of the previously added runnables, but we're - // OK with that. If we want to change the contract to guarantee ordering - // among runnables we'd have to modify the logic here to allow it. - executeListener(runnable, executor); - } - - /** - * Runs this execution list, executing all existing pairs in the order they - * were added. However, note that listeners added after this point may be - * executed before those previously added, and note that the execution order - * of all listeners is ultimately chosen by the implementations of the - * supplied executors. - * - *

This method is idempotent. Calling it several times in parallel is - * semantically equivalent to calling it exactly once. - * - * @since 10.0 (present in 1.0 as {@code run}) - */ - public void execute() { - // Lock while we update our state so the add method above will finish adding - // any listeners before we start to run them. - RunnableExecutorPair list; - synchronized (this) { - if (executed) { - return; - } - executed = true; - list = runnables; - runnables = null; // allow GC to free listeners even if this stays around for a while. - } - // If we succeeded then list holds all the runnables we to execute. The pairs in the stack are - // in the opposite order from how they were added so we need to reverse the list to fulfill our - // contract. - // This is somewhat annoying, but turns out to be very fast in practice. Alternatively, we - // could drop the contract on the method that enforces this queue like behavior since depending - // on it is likely to be a bug anyway. - - // N.B. All writes to the list and the next pointers must have happened before the above - // synchronized block, so we can iterate the list without the lock held here. - RunnableExecutorPair reversedList = null; - while (list != null) { - RunnableExecutorPair tmp = list; - list = list.next; - tmp.next = reversedList; - reversedList = tmp; - } - while (reversedList != null) { - executeListener(reversedList.runnable, reversedList.executor); - reversedList = reversedList.next; - } - } - - /** - * Submits the given runnable to the given {@link Executor} catching and logging all - * {@linkplain RuntimeException runtime exceptions} thrown by the executor. - */ - private static void executeListener(Runnable runnable, Executor executor) { - try { - executor.execute(runnable); - } catch (RuntimeException e) { - // Log it and keep going, bad runnable and/or executor. Don't - // punish the other runnables if we're given a bad one. We only - // catch RuntimeException because we want Errors to propagate up. - log.log(Level.SEVERE, "RuntimeException while executing runnable " - + runnable + " with executor " + executor, e); - } - } - - private static final class RunnableExecutorPair { - final Runnable runnable; - final Executor executor; - RunnableExecutorPair next; - - RunnableExecutorPair(Runnable runnable, Executor executor, RunnableExecutorPair next) { - this.runnable = runnable; - this.executor = executor; - this.next = next; - } - } -} diff --git a/java/src/game/future/FutureCallback.java b/java/src/game/future/FutureCallback.java deleted file mode 100644 index cdb9092..0000000 --- a/java/src/game/future/FutureCallback.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2011 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -/** - * A callback for accepting the results of a {@link java.util.concurrent.Future} - * computation asynchronously. - * - *

To attach to a {@link ListenableFuture} use {@link Futures#addCallback}. - * - * @author Anthony Zana - * @since 10.0 - */ -public interface FutureCallback { - /** - * Invoked with the result of the {@code Future} computation when it is - * successful. - */ - void onSuccess(V result); - - /** - * Invoked when a {@code Future} computation fails or is canceled. - * - *

If the future's {@link Future#get() get} method throws an {@link - * ExecutionException}, then the cause is passed to this method. Any other - * thrown object is passed unaltered. - */ - void onFailure(Throwable t); -} diff --git a/java/src/game/future/Futures.java b/java/src/game/future/Futures.java deleted file mode 100644 index b9ea72e..0000000 --- a/java/src/game/future/Futures.java +++ /dev/null @@ -1,1723 +0,0 @@ -/* - * Copyright (C) 2006 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; - -import game.collect.ImmutableList; -import game.collect.Sets; - -/** - * Static utility methods pertaining to the {@link Future} interface. - * - *

Many of these methods use the {@link ListenableFuture} API; consult the - * Guava User Guide article on - * {@code ListenableFuture}. - * - * @author Kevin Bourrillion - * @author Nishant Thakkar - * @author Sven Mawson - * @since 1.0 - */ -//@Beta -public final class Futures { - private Futures() {} - - /** - * Creates a {@link CheckedFuture} out of a normal {@link ListenableFuture} - * and a {@link Function} that maps from {@link Exception} instances into the - * appropriate checked type. - * - *

The given mapping function will be applied to an - * {@link InterruptedException}, a {@link CancellationException}, or an - * {@link ExecutionException}. - * See {@link Future#get()} for details on the exceptions thrown. - * - * @since 9.0 (source-compatible since 1.0) - */ -// public static CheckedFuture makeChecked( -// ListenableFuture future, Function mapper) { -// return new MappingCheckedFuture(checkNotNull(future), mapper); -// } - - private abstract static class ImmediateFuture - implements ListenableFuture { - - private static final Logger log = - Logger.getLogger(ImmediateFuture.class.getName()); - - @Override - public void addListener(Runnable listener, Executor executor) { -// checkNotNull(listener, "Runnable was null."); -// checkNotNull(executor, "Executor was null."); - try { - executor.execute(listener); - } catch (RuntimeException e) { - // ListenableFuture's contract is that it will not throw unchecked - // exceptions, so log the bad runnable and/or executor and swallow it. - log.log(Level.SEVERE, "RuntimeException while executing runnable " - + listener + " with executor " + executor, e); - } - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public abstract V get() throws ExecutionException; - - @Override - public V get(long timeout, TimeUnit unit) throws ExecutionException { -// checkNotNull(unit); - return get(); - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return true; - } - } - - private static class ImmediateSuccessfulFuture extends ImmediateFuture { - - private final V value; - - ImmediateSuccessfulFuture(V value) { - this.value = value; - } - - @Override - public V get() { - return value; - } - } - -// private static class ImmediateSuccessfulCheckedFuture -// extends ImmediateFuture implements CheckedFuture { -// -// private final V value; -// -// ImmediateSuccessfulCheckedFuture(V value) { -// this.value = value; -// } -// -// @Override -// public V get() { -// return value; -// } -// -// @Override -// public V checkedGet() { -// return value; -// } -// -// @Override -// public V checkedGet(long timeout, TimeUnit unit) { -// checkNotNull(unit); -// return value; -// } -// } - - private static class ImmediateFailedFuture extends ImmediateFuture { - - private final Throwable thrown; - - ImmediateFailedFuture(Throwable thrown) { - this.thrown = thrown; - } - - @Override - public V get() throws ExecutionException { - throw new ExecutionException(thrown); - } - } - -// private static class ImmediateCancelledFuture extends ImmediateFuture { -// -// private final CancellationException thrown; -// -// ImmediateCancelledFuture() { -// this.thrown = new CancellationException("Immediate cancelled future."); -// } -// -// @Override -// public boolean isCancelled() { -// return true; -// } -// -// @Override -// public V get() { -// throw AbstractFuture.cancellationExceptionWithCause( -// "Task was cancelled.", thrown); -// } -// } - -// private static class ImmediateFailedFuture -// extends ImmediateFuture implements ListenableFuture { -// -//// private final X thrown; -// -// ImmediateFailedCheckedFuture(X thrown) { -// this.thrown = thrown; -// } -// -// @Override -// public V get() throws ExecutionException { -// throw new ExecutionException(thrown); -// } -// -// @Override -// public V checkedGet() throws X { -// throw thrown; -// } -// -// @Override -// public V checkedGet(long timeout, TimeUnit unit) throws X { -// checkNotNull(unit); -// throw thrown; -// } -// } - - /** - * Creates a {@code ListenableFuture} which has its value set immediately upon - * construction. The getters just return the value. This {@code Future} can't - * be canceled or timed out and its {@code isDone()} method always returns - * {@code true}. - */ - public static ListenableFuture immediateFuture(V value) { - return new ImmediateSuccessfulFuture(value); - } - - /** - * Returns a {@code CheckedFuture} which has its value set immediately upon - * construction. - * - *

The returned {@code Future} can't be cancelled, and its {@code isDone()} - * method always returns {@code true}. Calling {@code get()} or {@code - * checkedGet()} will immediately return the provided value. - */ -// public static CheckedFuture -// immediateCheckedFuture(V value) { -// return new ImmediateSuccessfulCheckedFuture(value); -// } - - /** - * Returns a {@code ListenableFuture} which has an exception set immediately - * upon construction. - * - *

The returned {@code Future} can't be cancelled, and its {@code isDone()} - * method always returns {@code true}. Calling {@code get()} will immediately - * throw the provided {@code Throwable} wrapped in an {@code - * ExecutionException}. - */ - public static ListenableFuture immediateFailedFuture( - Throwable throwable) { -// checkNotNull(throwable); - return new ImmediateFailedFuture(throwable); - } - - /** - * Creates a {@code ListenableFuture} which is cancelled immediately upon - * construction, so that {@code isCancelled()} always returns {@code true}. - * - * @since 14.0 - */ -// public static ListenableFuture immediateCancelledFuture() { -// return new ImmediateCancelledFuture(); -// } - - /** - * Returns a {@code CheckedFuture} which has an exception set immediately upon - * construction. - * - *

The returned {@code Future} can't be cancelled, and its {@code isDone()} - * method always returns {@code true}. Calling {@code get()} will immediately - * throw the provided {@code Exception} wrapped in an {@code - * ExecutionException}, and calling {@code checkedGet()} will throw the - * provided exception itself. - */ -// public static ListenableFuture -// immediateFailedCheckedFuture(X exception) { -// checkNotNull(exception); -// return new ImmediateFailedCheckedFuture(exception); -// } - - /** - * Returns a {@code Future} whose result is taken from the given primary - * {@code input} or, if the primary input fails, from the {@code Future} - * provided by the {@code fallback}. {@link FutureFallback#create} is not - * invoked until the primary input has failed, so if the primary input - * succeeds, it is never invoked. If, during the invocation of {@code - * fallback}, an exception is thrown, this exception is used as the result of - * the output {@code Future}. - * - *

Below is an example of a fallback that returns a default value if an - * exception occurs: - * - *

   {@code
-   *   ListenableFuture fetchCounterFuture = ...;
-   *
-   *   // Falling back to a zero counter in case an exception happens when
-   *   // processing the RPC to fetch counters.
-   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
-   *       fetchCounterFuture, new FutureFallback() {
-   *         public ListenableFuture create(Throwable t) {
-   *           // Returning "0" as the default for the counter when the
-   *           // exception happens.
-   *           return immediateFuture(0);
-   *         }
-   *       });}
- * - *

The fallback can also choose to propagate the original exception when - * desired: - * - *

   {@code
-   *   ListenableFuture fetchCounterFuture = ...;
-   *
-   *   // Falling back to a zero counter only in case the exception was a
-   *   // TimeoutException.
-   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
-   *       fetchCounterFuture, new FutureFallback() {
-   *         public ListenableFuture create(Throwable t) {
-   *           if (t instanceof TimeoutException) {
-   *             return immediateFuture(0);
-   *           }
-   *           return immediateFailedFuture(t);
-   *         }
-   *       });}
- * - *

Note: If the derived {@code Future} is slow or heavyweight to create - * (whether the {@code Future} itself is slow or heavyweight to complete is - * irrelevant), consider {@linkplain #withFallback(ListenableFuture, - * FutureFallback, Executor) supplying an executor}. If you do not supply an - * executor, {@code withFallback} will use {@link - * MoreExecutors#sameThreadExecutor sameThreadExecutor}, which carries some - * caveats for heavier operations. For example, the call to {@code - * fallback.create} may run on an unpredictable or undesirable thread: - * - *

    - *
  • If the input {@code Future} is done at the time {@code withFallback} - * is called, {@code withFallback} will call {@code fallback.create} inline. - *
  • If the input {@code Future} is not yet done, {@code withFallback} will - * schedule {@code fallback.create} to be run by the thread that completes - * the input {@code Future}, which may be an internal system thread such as - * an RPC network thread. - *
- * - *

Also note that, regardless of which thread executes the {@code - * sameThreadExecutor} {@code fallback.create}, all other registered but - * unexecuted listeners are prevented from running during its execution, even - * if those listeners are to run in other executors. - * - * @param input the primary input {@code Future} - * @param fallback the {@link FutureFallback} implementation to be called if - * {@code input} fails - * @since 14.0 - */ -// public static ListenableFuture withFallback( -// ListenableFuture input, -// FutureFallback fallback) { -// return withFallback(input, fallback, sameThreadExecutor()); -// } - - /** - * Returns a {@code Future} whose result is taken from the given primary - * {@code input} or, if the primary input fails, from the {@code Future} - * provided by the {@code fallback}. {@link FutureFallback#create} is not - * invoked until the primary input has failed, so if the primary input - * succeeds, it is never invoked. If, during the invocation of {@code - * fallback}, an exception is thrown, this exception is used as the result of - * the output {@code Future}. - * - *

Below is an example of a fallback that returns a default value if an - * exception occurs: - * - *

   {@code
-   *   ListenableFuture fetchCounterFuture = ...;
-   *
-   *   // Falling back to a zero counter in case an exception happens when
-   *   // processing the RPC to fetch counters.
-   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
-   *       fetchCounterFuture, new FutureFallback() {
-   *         public ListenableFuture create(Throwable t) {
-   *           // Returning "0" as the default for the counter when the
-   *           // exception happens.
-   *           return immediateFuture(0);
-   *         }
-   *       }, sameThreadExecutor());}
- * - *

The fallback can also choose to propagate the original exception when - * desired: - * - *

   {@code
-   *   ListenableFuture fetchCounterFuture = ...;
-   *
-   *   // Falling back to a zero counter only in case the exception was a
-   *   // TimeoutException.
-   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
-   *       fetchCounterFuture, new FutureFallback() {
-   *         public ListenableFuture create(Throwable t) {
-   *           if (t instanceof TimeoutException) {
-   *             return immediateFuture(0);
-   *           }
-   *           return immediateFailedFuture(t);
-   *         }
-   *       }, sameThreadExecutor());}
- * - *

When the execution of {@code fallback.create} is fast and lightweight - * (though the {@code Future} it returns need not meet these criteria), - * consider {@linkplain #withFallback(ListenableFuture, FutureFallback) - * omitting the executor} or explicitly specifying {@code - * sameThreadExecutor}. However, be aware of the caveats documented in the - * link above. - * - * @param input the primary input {@code Future} - * @param fallback the {@link FutureFallback} implementation to be called if - * {@code input} fails - * @param executor the executor that runs {@code fallback} if {@code input} - * fails - * @since 14.0 - */ -// public static ListenableFuture withFallback( -// ListenableFuture input, -// FutureFallback fallback, Executor executor) { -// checkNotNull(fallback); -// return new FallbackFuture(input, fallback, executor); -// } - - /** - * A future that falls back on a second, generated future, in case its - * original future fails. - */ -// private static class FallbackFuture extends AbstractFuture { -// -// private volatile ListenableFuture running; -// -// FallbackFuture(ListenableFuture input, -// final FutureFallback fallback, -// final Executor executor) { -// running = input; -// addCallback(running, new FutureCallback() { -// @Override -// public void onSuccess(V value) { -// set(value); -// } -// -// @Override -// public void onFailure(Throwable t) { -// if (isCancelled()) { -// return; -// } -// try { -// running = fallback.create(t); -// if (isCancelled()) { // in case cancel called in the meantime -// running.cancel(wasInterrupted()); -// return; -// } -// addCallback(running, new FutureCallback() { -// @Override -// public void onSuccess(V value) { -// set(value); -// } -// -// @Override -// public void onFailure(Throwable t) { -// if (running.isCancelled()) { -// cancel(false); -// } else { -// setException(t); -// } -// } -// }, sameThreadExecutor()); -// } catch (Throwable e) { -// setException(e); -// } -// } -// }, executor); -// } -// -// @Override -// public boolean cancel(boolean mayInterruptIfRunning) { -// if (super.cancel(mayInterruptIfRunning)) { -// running.cancel(mayInterruptIfRunning); -// return true; -// } -// return false; -// } -// } - - /** - * Returns a new {@code ListenableFuture} whose result is asynchronously - * derived from the result of the given {@code Future}. More precisely, the - * returned {@code Future} takes its result from a {@code Future} produced by - * applying the given {@code AsyncFunction} to the result of the original - * {@code Future}. Example: - * - *

   {@code
-   *   ListenableFuture rowKeyFuture = indexService.lookUp(query);
-   *   AsyncFunction queryFunction =
-   *       new AsyncFunction() {
-   *         public ListenableFuture apply(RowKey rowKey) {
-   *           return dataService.read(rowKey);
-   *         }
-   *       };
-   *   ListenableFuture queryFuture =
-   *       transform(rowKeyFuture, queryFunction);}
- * - *

Note: If the derived {@code Future} is slow or heavyweight to create - * (whether the {@code Future} itself is slow or heavyweight to complete is - * irrelevant), consider {@linkplain #transform(ListenableFuture, - * AsyncFunction, Executor) supplying an executor}. If you do not supply an - * executor, {@code transform} will use {@link - * MoreExecutors#sameThreadExecutor sameThreadExecutor}, which carries some - * caveats for heavier operations. For example, the call to {@code - * function.apply} may run on an unpredictable or undesirable thread: - * - *

    - *
  • If the input {@code Future} is done at the time {@code transform} is - * called, {@code transform} will call {@code function.apply} inline. - *
  • If the input {@code Future} is not yet done, {@code transform} will - * schedule {@code function.apply} to be run by the thread that completes the - * input {@code Future}, which may be an internal system thread such as an - * RPC network thread. - *
- * - *

Also note that, regardless of which thread executes the {@code - * sameThreadExecutor} {@code function.apply}, all other registered but - * unexecuted listeners are prevented from running during its execution, even - * if those listeners are to run in other executors. - * - *

The returned {@code Future} attempts to keep its cancellation state in - * sync with that of the input future and that of the future returned by the - * function. That is, if the returned {@code Future} is cancelled, it will - * attempt to cancel the other two, and if either of the other two is - * cancelled, the returned {@code Future} will receive a callback in which it - * will attempt to cancel itself. - * - * @param input The future to transform - * @param function A function to transform the result of the input future - * to the result of the output future - * @return A future that holds result of the function (if the input succeeded) - * or the original input's failure (if not) - * @since 11.0 - */ -// public static ListenableFuture transform(ListenableFuture input, -// AsyncFunction function) { -// return transform(input, function, MoreExecutors.sameThreadExecutor()); -// } - - /** - * Returns a new {@code ListenableFuture} whose result is asynchronously - * derived from the result of the given {@code Future}. More precisely, the - * returned {@code Future} takes its result from a {@code Future} produced by - * applying the given {@code AsyncFunction} to the result of the original - * {@code Future}. Example: - * - *

   {@code
-   *   ListenableFuture rowKeyFuture = indexService.lookUp(query);
-   *   AsyncFunction queryFunction =
-   *       new AsyncFunction() {
-   *         public ListenableFuture apply(RowKey rowKey) {
-   *           return dataService.read(rowKey);
-   *         }
-   *       };
-   *   ListenableFuture queryFuture =
-   *       transform(rowKeyFuture, queryFunction, executor);}
- * - *

The returned {@code Future} attempts to keep its cancellation state in - * sync with that of the input future and that of the future returned by the - * chain function. That is, if the returned {@code Future} is cancelled, it - * will attempt to cancel the other two, and if either of the other two is - * cancelled, the returned {@code Future} will receive a callback in which it - * will attempt to cancel itself. - * - *

When the execution of {@code function.apply} is fast and lightweight - * (though the {@code Future} it returns need not meet these criteria), - * consider {@linkplain #transform(ListenableFuture, AsyncFunction) omitting - * the executor} or explicitly specifying {@code sameThreadExecutor}. - * However, be aware of the caveats documented in the link above. - * - * @param input The future to transform - * @param function A function to transform the result of the input future - * to the result of the output future - * @param executor Executor to run the function in. - * @return A future that holds result of the function (if the input succeeded) - * or the original input's failure (if not) - * @since 11.0 - */ -// public static ListenableFuture transform(ListenableFuture input, -// AsyncFunction function, -// Executor executor) { -// ChainingListenableFuture output = -// new ChainingListenableFuture(function, input); -// input.addListener(output, executor); -// return output; -// } - - /** - * Returns a new {@code ListenableFuture} whose result is the product of - * applying the given {@code Function} to the result of the given {@code - * Future}. Example: - * - *

   {@code
-   *   ListenableFuture queryFuture = ...;
-   *   Function> rowsFunction =
-   *       new Function>() {
-   *         public List apply(QueryResult queryResult) {
-   *           return queryResult.getRows();
-   *         }
-   *       };
-   *   ListenableFuture> rowsFuture =
-   *       transform(queryFuture, rowsFunction);}
- * - *

Note: If the transformation is slow or heavyweight, consider {@linkplain - * #transform(ListenableFuture, Function, Executor) supplying an executor}. - * If you do not supply an executor, {@code transform} will use {@link - * MoreExecutors#sameThreadExecutor sameThreadExecutor}, which carries some - * caveats for heavier operations. For example, the call to {@code - * function.apply} may run on an unpredictable or undesirable thread: - * - *

    - *
  • If the input {@code Future} is done at the time {@code transform} is - * called, {@code transform} will call {@code function.apply} inline. - *
  • If the input {@code Future} is not yet done, {@code transform} will - * schedule {@code function.apply} to be run by the thread that completes the - * input {@code Future}, which may be an internal system thread such as an - * RPC network thread. - *
- * - *

Also note that, regardless of which thread executes the {@code - * sameThreadExecutor} {@code function.apply}, all other registered but - * unexecuted listeners are prevented from running during its execution, even - * if those listeners are to run in other executors. - * - *

The returned {@code Future} attempts to keep its cancellation state in - * sync with that of the input future. That is, if the returned {@code Future} - * is cancelled, it will attempt to cancel the input, and if the input is - * cancelled, the returned {@code Future} will receive a callback in which it - * will attempt to cancel itself. - * - *

An example use of this method is to convert a serializable object - * returned from an RPC into a POJO. - * - * @param input The future to transform - * @param function A Function to transform the results of the provided future - * to the results of the returned future. This will be run in the thread - * that notifies input it is complete. - * @return A future that holds result of the transformation. - * @since 9.0 (in 1.0 as {@code compose}) - */ -// public static ListenableFuture transform(ListenableFuture input, -// final Function function) { -// return transform(input, function, MoreExecutors.sameThreadExecutor()); -// } - - /** - * Returns a new {@code ListenableFuture} whose result is the product of - * applying the given {@code Function} to the result of the given {@code - * Future}. Example: - * - *

   {@code
-   *   ListenableFuture queryFuture = ...;
-   *   Function> rowsFunction =
-   *       new Function>() {
-   *         public List apply(QueryResult queryResult) {
-   *           return queryResult.getRows();
-   *         }
-   *       };
-   *   ListenableFuture> rowsFuture =
-   *       transform(queryFuture, rowsFunction, executor);}
- * - *

The returned {@code Future} attempts to keep its cancellation state in - * sync with that of the input future. That is, if the returned {@code Future} - * is cancelled, it will attempt to cancel the input, and if the input is - * cancelled, the returned {@code Future} will receive a callback in which it - * will attempt to cancel itself. - * - *

An example use of this method is to convert a serializable object - * returned from an RPC into a POJO. - * - *

When the transformation is fast and lightweight, consider {@linkplain - * #transform(ListenableFuture, Function) omitting the executor} or - * explicitly specifying {@code sameThreadExecutor}. However, be aware of the - * caveats documented in the link above. - * - * @param input The future to transform - * @param function A Function to transform the results of the provided future - * to the results of the returned future. - * @param executor Executor to run the function in. - * @return A future that holds result of the transformation. - * @since 9.0 (in 2.0 as {@code compose}) - */ -// public static ListenableFuture transform(ListenableFuture input, -// final Function function, Executor executor) { -// checkNotNull(function); -// AsyncFunction wrapperFunction -// = new AsyncFunction() { -// @Override public ListenableFuture apply(I input) { -// O output = function.apply(input); -// return immediateFuture(output); -// } -// }; -// return transform(input, wrapperFunction, executor); -// } - - /** - * Like {@link #transform(ListenableFuture, Function)} except that the - * transformation {@code function} is invoked on each call to - * {@link Future#get() get()} on the returned future. - * - *

The returned {@code Future} reflects the input's cancellation - * state directly, and any attempt to cancel the returned Future is likewise - * passed through to the input Future. - * - *

Note that calls to {@linkplain Future#get(long, TimeUnit) timed get} - * only apply the timeout to the execution of the underlying {@code Future}, - * not to the execution of the transformation function. - * - *

The primary audience of this method is callers of {@code transform} - * who don't have a {@code ListenableFuture} available and - * do not mind repeated, lazy function evaluation. - * - * @param input The future to transform - * @param function A Function to transform the results of the provided future - * to the results of the returned future. - * @return A future that returns the result of the transformation. - * @since 10.0 - */ -// public static Future lazyTransform(final Future input, -// final Function function) { -// checkNotNull(input); -// checkNotNull(function); -// return new Future() { -// -// @Override -// public boolean cancel(boolean mayInterruptIfRunning) { -// return input.cancel(mayInterruptIfRunning); -// } -// -// @Override -// public boolean isCancelled() { -// return input.isCancelled(); -// } -// -// @Override -// public boolean isDone() { -// return input.isDone(); -// } -// -// @Override -// public O get() throws InterruptedException, ExecutionException { -// return applyTransformation(input.get()); -// } -// -// @Override -// public O get(long timeout, TimeUnit unit) -// throws InterruptedException, ExecutionException, TimeoutException { -// return applyTransformation(input.get(timeout, unit)); -// } -// -// private O applyTransformation(I input) throws ExecutionException { -// try { -// return function.apply(input); -// } catch (Throwable t) { -// throw new ExecutionException(t); -// } -// } -// }; -// } - - /** - * An implementation of {@code ListenableFuture} that also implements - * {@code Runnable} so that it can be used to nest ListenableFutures. - * Once the passed-in {@code ListenableFuture} is complete, it calls the - * passed-in {@code Function} to generate the result. - * - *

For historical reasons, this class has a special case in its exception - * handling: If the given {@code AsyncFunction} throws an {@code - * UndeclaredThrowableException}, {@code ChainingListenableFuture} unwraps it - * and uses its cause as the output future's exception, rather than - * using the {@code UndeclaredThrowableException} itself as it would for other - * exception types. The reason for this is that {@code Futures.transform} used - * to require a {@code Function}, whose {@code apply} method is not allowed to - * throw checked exceptions. Nowadays, {@code Futures.transform} has an - * overload that accepts an {@code AsyncFunction}, whose {@code apply} method - * is allowed to throw checked exception. Users who wish to throw - * checked exceptions should use that overload instead, and we - * should remove the {@code UndeclaredThrowableException} special case. - */ -// private static class ChainingListenableFuture -// extends AbstractFuture implements Runnable { -// -// private AsyncFunction function; -// private ListenableFuture inputFuture; -// private volatile ListenableFuture outputFuture; -// private final CountDownLatch outputCreated = new CountDownLatch(1); -// -// private ChainingListenableFuture( -// AsyncFunction function, -// ListenableFuture inputFuture) { -// this.function = checkNotNull(function); -// this.inputFuture = checkNotNull(inputFuture); -// } -// -// @Override -// public boolean cancel(boolean mayInterruptIfRunning) { -// /* -// * Our additional cancellation work needs to occur even if -// * !mayInterruptIfRunning, so we can't move it into interruptTask(). -// */ -// if (super.cancel(mayInterruptIfRunning)) { -// // This should never block since only one thread is allowed to cancel -// // this Future. -// cancel(inputFuture, mayInterruptIfRunning); -// cancel(outputFuture, mayInterruptIfRunning); -// return true; -// } -// return false; -// } -// -// private void cancel(Future future, -// boolean mayInterruptIfRunning) { -// if (future != null) { -// future.cancel(mayInterruptIfRunning); -// } -// } -// -// @Override -// public void run() { -// try { -// I sourceResult; -// try { -// sourceResult = getUninterruptibly(inputFuture); -// } catch (CancellationException e) { -// // Cancel this future and return. -// // At this point, inputFuture is cancelled and outputFuture doesn't -// // exist, so the value of mayInterruptIfRunning is irrelevant. -// cancel(false); -// return; -// } catch (ExecutionException e) { -// // Set the cause of the exception as this future's exception -// setException(e.getCause()); -// return; -// } -// -// final ListenableFuture outputFuture = this.outputFuture = -// Preconditions.checkNotNull(function.apply(sourceResult), -// "AsyncFunction may not return null."); -// if (isCancelled()) { -// outputFuture.cancel(wasInterrupted()); -// this.outputFuture = null; -// return; -// } -// outputFuture.addListener(new Runnable() { -// @Override -// public void run() { -// try { -// set(getUninterruptibly(outputFuture)); -// } catch (CancellationException e) { -// // Cancel this future and return. -// // At this point, inputFuture and outputFuture are done, so the -// // value of mayInterruptIfRunning is irrelevant. -// cancel(false); -// return; -// } catch (ExecutionException e) { -// // Set the cause of the exception as this future's exception -// setException(e.getCause()); -// } finally { -// // Don't pin inputs beyond completion -// ChainingListenableFuture.this.outputFuture = null; -// } -// } -// }, MoreExecutors.sameThreadExecutor()); -// } catch (UndeclaredThrowableException e) { -// // Set the cause of the exception as this future's exception -// setException(e.getCause()); -// } catch (Throwable t) { -// // This exception is irrelevant in this thread, but useful for the -// // client -// setException(t); -// } finally { -// // Don't pin inputs beyond completion -// function = null; -// inputFuture = null; -// // Allow our get routines to examine outputFuture now. -// outputCreated.countDown(); -// } -// } -// } - - /** - * Returns a new {@code ListenableFuture} whose result is the product of - * calling {@code get()} on the {@code Future} nested within the given {@code - * Future}, effectively chaining the futures one after the other. Example: - * - *

   {@code
-   *   SettableFuture> nested = SettableFuture.create();
-   *   ListenableFuture dereferenced = dereference(nested);}
- * - *

This call has the same cancellation and execution semantics as {@link - * #transform(ListenableFuture, AsyncFunction)}, in that the returned {@code - * Future} attempts to keep its cancellation state in sync with both the - * input {@code Future} and the nested {@code Future}. The transformation - * is very lightweight and therefore takes place in the same thread (either - * the thread that called {@code dereference}, or the thread in which the - * dereferenced future completes). - * - * @param nested The nested future to transform. - * @return A future that holds result of the inner future. - * @since 13.0 - */ -// -// public static ListenableFuture dereference( -// ListenableFuture> nested) { -// return Futures.transform((ListenableFuture) nested, (AsyncFunction) DEREFERENCER); -// } - - /** - * Helper {@code Function} for {@link #dereference}. - */ -// private static final AsyncFunction, Object> DEREFERENCER = -// new AsyncFunction, Object>() { -// @Override public ListenableFuture apply(ListenableFuture input) { -// return input; -// } -// }; - - /** - * Creates a new {@code ListenableFuture} whose value is a list containing the - * values of all its input futures, if all succeed. If any input fails, the - * returned future fails. - * - *

The list of results is in the same order as the input list. - * - *

Canceling this future will attempt to cancel all the component futures, - * and if any of the provided futures fails or is canceled, this one is, - * too. - * - * @param futures futures to combine - * @return a future that provides a list of the results of the component - * futures - * @since 10.0 - */ -// @Beta -// public static ListenableFuture> allAsList( -// ListenableFuture... futures) { -// return listFuture(ImmutableList.copyOf(futures), true, -// MoreExecutors.sameThreadExecutor()); -// } - - /** - * Creates a new {@code ListenableFuture} whose value is a list containing the - * values of all its input futures, if all succeed. If any input fails, the - * returned future fails. - * - *

The list of results is in the same order as the input list. - * - *

Canceling this future will attempt to cancel all the component futures, - * and if any of the provided futures fails or is canceled, this one is, - * too. - * - * @param futures futures to combine - * @return a future that provides a list of the results of the component - * futures - * @since 10.0 - */ -// @Beta - public static ListenableFuture> allAsList( - Iterable> futures) { - return listFuture(ImmutableList.copyOf(futures), true, - MoreExecutors.sameThreadExecutor()); - } - - /** - * Creates a new {@code ListenableFuture} whose result is set from the - * supplied future when it completes. Cancelling the supplied future - * will also cancel the returned future, but cancelling the returned - * future will have no effect on the supplied future. - * - * @since 15.0 - */ -// public static ListenableFuture nonCancellationPropagating( -// ListenableFuture future) { -// return new NonCancellationPropagatingFuture(future); -// } - - /** - * A wrapped future that does not propagate cancellation to its delegate. - */ -// private static class NonCancellationPropagatingFuture -// extends AbstractFuture { -// NonCancellationPropagatingFuture(final ListenableFuture delegate) { -// checkNotNull(delegate); -// addCallback(delegate, new FutureCallback() { -// @Override -// public void onSuccess(V result) { -// set(result); -// } -// -// @Override -// public void onFailure(Throwable t) { -// if (delegate.isCancelled()) { -// cancel(false); -// } else { -// setException(t); -// } -// } -// }, sameThreadExecutor()); -// } -// } - - /** - * Creates a new {@code ListenableFuture} whose value is a list containing the - * values of all its successful input futures. The list of results is in the - * same order as the input list, and if any of the provided futures fails or - * is canceled, its corresponding position will contain {@code null} (which is - * indistinguishable from the future having a successful value of - * {@code null}). - * - *

Canceling this future will attempt to cancel all the component futures. - * - * @param futures futures to combine - * @return a future that provides a list of the results of the component - * futures - * @since 10.0 - */ -// @Beta -// public static ListenableFuture> successfulAsList( -// ListenableFuture... futures) { -// return listFuture(ImmutableList.copyOf(futures), false, -// MoreExecutors.sameThreadExecutor()); -// } - - /** - * Creates a new {@code ListenableFuture} whose value is a list containing the - * values of all its successful input futures. The list of results is in the - * same order as the input list, and if any of the provided futures fails or - * is canceled, its corresponding position will contain {@code null} (which is - * indistinguishable from the future having a successful value of - * {@code null}). - * - *

Canceling this future will attempt to cancel all the component futures. - * - * @param futures futures to combine - * @return a future that provides a list of the results of the component - * futures - * @since 10.0 - */ -// @Beta -// public static ListenableFuture> successfulAsList( -// Iterable> futures) { -// return listFuture(ImmutableList.copyOf(futures), false, -// MoreExecutors.sameThreadExecutor()); -// } - - /** - * Returns a list of delegate futures that correspond to the futures received in the order - * that they complete. Delegate futures return the same value or throw the same exception - * as the corresponding input future returns/throws. - * - *

Cancelling a delegate future has no effect on any input future, since the delegate future - * does not correspond to a specific input future until the appropriate number of input - * futures have completed. At that point, it is too late to cancel the input future. - * The input future's result, which cannot be stored into the cancelled delegate future, - * is ignored. - * - * @since 17.0 - */ -// @Beta -// public static ImmutableList> inCompletionOrder( -// Iterable> futures) { -// // A CLQ may be overkill here. We could save some pointers/memory by synchronizing on an -// // ArrayDeque -// final ConcurrentLinkedQueue> delegates = -// Queues.newConcurrentLinkedQueue(); -// ImmutableList.Builder> listBuilder = ImmutableList.builder(); -// // Using SerializingExecutor here will ensure that each CompletionOrderListener executes -// // atomically and therefore that each returned future is guaranteed to be in completion order. -// // N.B. there are some cases where the use of this executor could have possibly surprising -// // effects when input futures finish at approximately the same time _and_ the output futures -// // have sameThreadExecutor listeners. In this situation, the listeners may end up running on a -// // different thread than if they were attached to the corresponding input future. We believe -// // this to be a negligible cost since: -// // 1. Using the sameThreadExecutor implies that your callback is safe to run on any thread. -// // 2. This would likely only be noticeable if you were doing something expensive or blocking on -// // a sameThreadExecutor listener on one of the output futures which is an antipattern anyway. -// SerializingExecutor executor = new SerializingExecutor(MoreExecutors.sameThreadExecutor()); -// for (final ListenableFuture future : futures) { -// AsyncSettableFuture delegate = AsyncSettableFuture.create(); -// // Must make sure to add the delegate to the queue first in case the future is already done -// delegates.add(delegate); -// future.addListener(new Runnable() { -// @Override public void run() { -// delegates.remove().setFuture(future); -// } -// }, executor); -// listBuilder.add(delegate); -// } -// return listBuilder.build(); -// } - - /** - * Registers separate success and failure callbacks to be run when the {@code - * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone() - * complete} or, if the computation is already complete, immediately. - * - *

There is no guaranteed ordering of execution of callbacks, but any - * callback added through this method is guaranteed to be called once the - * computation is complete. - * - * Example:

 {@code
-   * ListenableFuture future = ...;
-   * addCallback(future,
-   *     new FutureCallback {
-   *       public void onSuccess(QueryResult result) {
-   *         storeInCache(result);
-   *       }
-   *       public void onFailure(Throwable t) {
-   *         reportError(t);
-   *       }
-   *     });}
- * - *

Note: If the callback is slow or heavyweight, consider {@linkplain - * #addCallback(ListenableFuture, FutureCallback, Executor) supplying an - * executor}. If you do not supply an executor, {@code addCallback} will use - * {@link MoreExecutors#sameThreadExecutor sameThreadExecutor}, which carries - * some caveats for heavier operations. For example, the callback may run on - * an unpredictable or undesirable thread: - * - *

    - *
  • If the input {@code Future} is done at the time {@code addCallback} is - * called, {@code addCallback} will execute the callback inline. - *
  • If the input {@code Future} is not yet done, {@code addCallback} will - * schedule the callback to be run by the thread that completes the input - * {@code Future}, which may be an internal system thread such as an RPC - * network thread. - *
- * - *

Also note that, regardless of which thread executes the {@code - * sameThreadExecutor} callback, all other registered but unexecuted listeners - * are prevented from running during its execution, even if those listeners - * are to run in other executors. - * - *

For a more general interface to attach a completion listener to a - * {@code Future}, see {@link ListenableFuture#addListener addListener}. - * - * @param future The future attach the callback to. - * @param callback The callback to invoke when {@code future} is completed. - * @since 10.0 - */ - public static void addCallback(ListenableFuture future, - FutureCallback callback) { - addCallback(future, callback, MoreExecutors.sameThreadExecutor()); - } - - /** - * Registers separate success and failure callbacks to be run when the {@code - * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone() - * complete} or, if the computation is already complete, immediately. - * - *

The callback is run in {@code executor}. - * There is no guaranteed ordering of execution of callbacks, but any - * callback added through this method is guaranteed to be called once the - * computation is complete. - * - * Example:

 {@code
-   * ListenableFuture future = ...;
-   * Executor e = ...
-   * addCallback(future,
-   *     new FutureCallback {
-   *       public void onSuccess(QueryResult result) {
-   *         storeInCache(result);
-   *       }
-   *       public void onFailure(Throwable t) {
-   *         reportError(t);
-   *       }
-   *     }, e);}
- * - *

When the callback is fast and lightweight, consider {@linkplain - * #addCallback(ListenableFuture, FutureCallback) omitting the executor} or - * explicitly specifying {@code sameThreadExecutor}. However, be aware of the - * caveats documented in the link above. - * - *

For a more general interface to attach a completion listener to a - * {@code Future}, see {@link ListenableFuture#addListener addListener}. - * - * @param future The future attach the callback to. - * @param callback The callback to invoke when {@code future} is completed. - * @param executor The executor to run {@code callback} when the future - * completes. - * @since 10.0 - */ - public static void addCallback(final ListenableFuture future, - final FutureCallback callback, Executor executor) { - Runnable callbackListener = new Runnable() { - @Override - public void run() { - final V value; - try { - // TODO(user): (Before Guava release), validate that this - // is the thing for IE. - value = getUninterruptibly(future); - } catch (ExecutionException e) { - callback.onFailure(e.getCause()); - return; - } catch (RuntimeException e) { - callback.onFailure(e); - return; - } catch (Error e) { - callback.onFailure(e); - return; - } - callback.onSuccess(value); - } - }; - future.addListener(callbackListener, executor); - } - - /** - * Returns the result of {@link Future#get()}, converting most exceptions to a - * new instance of the given checked exception type. This reduces boilerplate - * for a common use of {@code Future} in which it is unnecessary to - * programmatically distinguish between exception types or to extract other - * information from the exception instance. - * - *

Exceptions from {@code Future.get} are treated as follows: - *

    - *
  • Any {@link ExecutionException} has its cause wrapped in an - * {@code X} if the cause is a checked exception, an {@link - * UncheckedExecutionException} if the cause is a {@code - * RuntimeException}, or an {@link ExecutionError} if the cause is an - * {@code Error}. - *
  • Any {@link InterruptedException} is wrapped in an {@code X} (after - * restoring the interrupt). - *
  • Any {@link CancellationException} is propagated untouched, as is any - * other {@link RuntimeException} (though {@code get} implementations are - * discouraged from throwing such exceptions). - *
- * - *

The overall principle is to continue to treat every checked exception as a - * checked exception, every unchecked exception as an unchecked exception, and - * every error as an error. In addition, the cause of any {@code - * ExecutionException} is wrapped in order to ensure that the new stack trace - * matches that of the current thread. - * - *

Instances of {@code exceptionClass} are created by choosing an arbitrary - * public constructor that accepts zero or more arguments, all of type {@code - * String} or {@code Throwable} (preferring constructors with at least one - * {@code String}) and calling the constructor via reflection. If the - * exception did not already have a cause, one is set by calling {@link - * Throwable#initCause(Throwable)} on it. If no such constructor exists, an - * {@code IllegalArgumentException} is thrown. - * - * @throws X if {@code get} throws any checked exception except for an {@code - * ExecutionException} whose cause is not itself a checked exception - * @throws UncheckedExecutionException if {@code get} throws an {@code - * ExecutionException} with a {@code RuntimeException} as its cause - * @throws ExecutionError if {@code get} throws an {@code ExecutionException} - * with an {@code Error} as its cause - * @throws CancellationException if {@code get} throws a {@code - * CancellationException} - * @throws IllegalArgumentException if {@code exceptionClass} extends {@code - * RuntimeException} or does not have a suitable constructor - * @since 10.0 - */ -// public static V get( -// Future future, Class exceptionClass) throws X { -// checkNotNull(future); -// checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), -// "Futures.get exception type (%s) must not be a RuntimeException", -// exceptionClass); -// try { -// return future.get(); -// } catch (InterruptedException e) { -// currentThread().interrupt(); -// throw newWithCause(exceptionClass, e); -// } catch (ExecutionException e) { -// wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); -// throw new AssertionError(); -// } -// } - - /** - * Returns the result of {@link Future#get(long, TimeUnit)}, converting most - * exceptions to a new instance of the given checked exception type. This - * reduces boilerplate for a common use of {@code Future} in which it is - * unnecessary to programmatically distinguish between exception types or to - * extract other information from the exception instance. - * - *

Exceptions from {@code Future.get} are treated as follows: - *

    - *
  • Any {@link ExecutionException} has its cause wrapped in an - * {@code X} if the cause is a checked exception, an {@link - * UncheckedExecutionException} if the cause is a {@code - * RuntimeException}, or an {@link ExecutionError} if the cause is an - * {@code Error}. - *
  • Any {@link InterruptedException} is wrapped in an {@code X} (after - * restoring the interrupt). - *
  • Any {@link TimeoutException} is wrapped in an {@code X}. - *
  • Any {@link CancellationException} is propagated untouched, as is any - * other {@link RuntimeException} (though {@code get} implementations are - * discouraged from throwing such exceptions). - *
- * - *

The overall principle is to continue to treat every checked exception as a - * checked exception, every unchecked exception as an unchecked exception, and - * every error as an error. In addition, the cause of any {@code - * ExecutionException} is wrapped in order to ensure that the new stack trace - * matches that of the current thread. - * - *

Instances of {@code exceptionClass} are created by choosing an arbitrary - * public constructor that accepts zero or more arguments, all of type {@code - * String} or {@code Throwable} (preferring constructors with at least one - * {@code String}) and calling the constructor via reflection. If the - * exception did not already have a cause, one is set by calling {@link - * Throwable#initCause(Throwable)} on it. If no such constructor exists, an - * {@code IllegalArgumentException} is thrown. - * - * @throws X if {@code get} throws any checked exception except for an {@code - * ExecutionException} whose cause is not itself a checked exception - * @throws UncheckedExecutionException if {@code get} throws an {@code - * ExecutionException} with a {@code RuntimeException} as its cause - * @throws ExecutionError if {@code get} throws an {@code ExecutionException} - * with an {@code Error} as its cause - * @throws CancellationException if {@code get} throws a {@code - * CancellationException} - * @throws IllegalArgumentException if {@code exceptionClass} extends {@code - * RuntimeException} or does not have a suitable constructor - * @since 10.0 - */ -// public static V get( -// Future future, long timeout, TimeUnit unit, Class exceptionClass) -// throws X { -// checkNotNull(future); -// checkNotNull(unit); -// checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), -// "Futures.get exception type (%s) must not be a RuntimeException", -// exceptionClass); -// try { -// return future.get(timeout, unit); -// } catch (InterruptedException e) { -// currentThread().interrupt(); -// throw newWithCause(exceptionClass, e); -// } catch (TimeoutException e) { -// throw newWithCause(exceptionClass, e); -// } catch (ExecutionException e) { -// wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); -// throw new AssertionError(); -// } -// } - -// private static void wrapAndThrowExceptionOrError( -// Throwable cause, Class exceptionClass) throws X { -// if (cause instanceof Error) { -// throw new ExecutionError((Error) cause); -// } -// if (cause instanceof RuntimeException) { -// throw new UncheckedExecutionException(cause); -// } -// throw newWithCause(exceptionClass, cause); -// } - - /** - * Returns the result of calling {@link Future#get()} uninterruptibly on a - * task known not to throw a checked exception. This makes {@code Future} more - * suitable for lightweight, fast-running tasks that, barring bugs in the - * code, will not fail. This gives it exception-handling behavior similar to - * that of {@code ForkJoinTask.join}. - * - *

Exceptions from {@code Future.get} are treated as follows: - *

    - *
  • Any {@link ExecutionException} has its cause wrapped in an - * {@link UncheckedExecutionException} (if the cause is an {@code - * Exception}) or {@link ExecutionError} (if the cause is an {@code - * Error}). - *
  • Any {@link InterruptedException} causes a retry of the {@code get} - * call. The interrupt is restored before {@code getUnchecked} returns. - *
  • Any {@link CancellationException} is propagated untouched. So is any - * other {@link RuntimeException} ({@code get} implementations are - * discouraged from throwing such exceptions). - *
- * - *

The overall principle is to eliminate all checked exceptions: to loop to - * avoid {@code InterruptedException}, to pass through {@code - * CancellationException}, and to wrap any exception from the underlying - * computation in an {@code UncheckedExecutionException} or {@code - * ExecutionError}. - * - *

For an uninterruptible {@code get} that preserves other exceptions, see - * {@link Uninterruptibles#getUninterruptibly(Future)}. - * - * @throws UncheckedExecutionException if {@code get} throws an {@code - * ExecutionException} with an {@code Exception} as its cause - * @throws ExecutionError if {@code get} throws an {@code ExecutionException} - * with an {@code Error} as its cause - * @throws CancellationException if {@code get} throws a {@code - * CancellationException} - * @since 10.0 - */ - public static V getUnchecked(Future future) { -// checkNotNull(future); - try { - return getUninterruptibly(future); - } catch (ExecutionException e) { - wrapAndThrowUnchecked(e.getCause()); - throw new AssertionError(); - } - } - - public static V getUninterruptibly(Future future) - throws ExecutionException { - boolean interrupted = false; - try { - while (true) { - try { - return future.get(); - } catch (InterruptedException e) { - interrupted = true; - } - } - } finally { - if (interrupted) { - Thread.currentThread().interrupt(); - } - } - } - - private static void wrapAndThrowUnchecked(Throwable cause) { - if (cause instanceof Error) { - throw new ExecutionError((Error) cause); - } - /* - * It's a non-Error, non-Exception Throwable. From my survey of such - * classes, I believe that most users intended to extend Exception, so we'll - * treat it like an Exception. - */ - throw new UncheckedExecutionException(cause); - } - - /* - * TODO(user): FutureChecker interface for these to be static methods on? If - * so, refer to it in the (static-method) Futures.get documentation - */ - - /* - * Arguably we don't need a timed getUnchecked because any operation slow - * enough to require a timeout is heavyweight enough to throw a checked - * exception and therefore be inappropriate to use with getUnchecked. Further, - * it's not clear that converting the checked TimeoutException to a - * RuntimeException -- especially to an UncheckedExecutionException, since it - * wasn't thrown by the computation -- makes sense, and if we don't convert - * it, the user still has to write a try-catch block. - * - * If you think you would use this method, let us know. - */ - -// private static X newWithCause( -// Class exceptionClass, Throwable cause) { -// // getConstructors() guarantees this as long as we don't modify the array. -// -// List> constructors = -// (List) Arrays.asList(exceptionClass.getConstructors()); -// for (Constructor constructor : preferringStrings(constructors)) { -// X instance = newFromConstructor(constructor, cause); -// if (instance != null) { -// if (instance.getCause() == null) { -// instance.initCause(cause); -// } -// return instance; -// } -// } -// throw new IllegalArgumentException( -// "No appropriate constructor for exception of type " + exceptionClass -// + " in response to chained exception", cause); -// } - -// private static List> -// preferringStrings(List> constructors) { -// return WITH_STRING_PARAM_FIRST.sortedCopy(constructors); -// } -// -// private static final Ordering> WITH_STRING_PARAM_FIRST = -// Ordering.natural().onResultOf(new Function, Boolean>() { -// @Override public Boolean apply(Constructor input) { -// return asList(input.getParameterTypes()).contains(String.class); -// } -// }).reverse(); - -// private static X newFromConstructor( -// Constructor constructor, Throwable cause) { -// Class[] paramTypes = constructor.getParameterTypes(); -// Object[] params = new Object[paramTypes.length]; -// for (int i = 0; i < paramTypes.length; i++) { -// Class paramType = paramTypes[i]; -// if (paramType.equals(String.class)) { -// params[i] = cause.toString(); -// } else if (paramType.equals(Throwable.class)) { -// params[i] = cause; -// } else { -// return null; -// } -// } -// try { -// return constructor.newInstance(params); -// } catch (IllegalArgumentException e) { -// return null; -// } catch (InstantiationException e) { -// return null; -// } catch (IllegalAccessException e) { -// return null; -// } catch (InvocationTargetException e) { -// return null; -// } -// } - - private interface FutureCombiner { - C combine(List values); - } - - private static class CombinedFuture extends AbstractFuture> { - private static final Logger logger = - Logger.getLogger(CombinedFuture.class.getName()); - - ImmutableList> futures; - final boolean allMustSucceed; - final AtomicInteger remaining; -// FutureCombiner combiner; - List values; - final Object seenExceptionsLock = new Object(); - Set seenExceptions; - - CombinedFuture( - ImmutableList> futures, - boolean allMustSucceed, Executor listenerExecutor // , -// FutureCombiner combiner - ) { - this.futures = futures; - this.allMustSucceed = allMustSucceed; - this.remaining = new AtomicInteger(futures.size()); -// this.combiner = combiner; - this.values = new ArrayList(futures.size()); - init(listenerExecutor); - } - - /** - * Must be called at the end of the constructor. - */ - protected void init(final Executor listenerExecutor) { - // First, schedule cleanup to execute when the Future is done. - addListener(new Runnable() { - @Override - public void run() { - // Cancel all the component futures. - if (CombinedFuture.this.isCancelled()) { - for (ListenableFuture future : CombinedFuture.this.futures) { - future.cancel(CombinedFuture.this.wasInterrupted()); - } - } - - // Let go of the memory held by other futures - CombinedFuture.this.futures = null; - - // By now the values array has either been set as the Future's value, - // or (in case of failure) is no longer useful. - CombinedFuture.this.values = null; - - // The combiner may also hold state, so free that as well -// CombinedFuture.this.combiner = null; - } - }, MoreExecutors.sameThreadExecutor()); - - // Now begin the "real" initialization. - - // Corner case: List is empty. - if (futures.isEmpty()) { - set(ImmutableList.of()); - return; - } - - // Populate the results list with null initially. - for (int i = 0; i < futures.size(); ++i) { - values.add(null); - } - - // Register a listener on each Future in the list to update - // the state of this future. - // Note that if all the futures on the list are done prior to completing - // this loop, the last call to addListener() will callback to - // setOneValue(), transitively call our cleanup listener, and set - // this.futures to null. - // This is not actually a problem, since the foreach only needs - // this.futures to be non-null at the beginning of the loop. - int i = 0; - for (final ListenableFuture listenable : futures) { - final int index = i++; - listenable.addListener(new Runnable() { - @Override - public void run() { - setOneValue(index, listenable); - } - }, listenerExecutor); - } - } - - /** - * Fails this future with the given Throwable if {@link #allMustSucceed} is - * true. Also, logs the throwable if it is an {@link Error} or if - * {@link #allMustSucceed} is {@code true}, the throwable did not cause - * this future to fail, and it is the first time we've seen that particular Throwable. - */ - private void setExceptionAndMaybeLog(Throwable throwable) { - boolean visibleFromOutputFuture = false; - boolean firstTimeSeeingThisException = true; - if (allMustSucceed) { - // As soon as the first one fails, throw the exception up. - // The result of all other inputs is then ignored. - visibleFromOutputFuture = super.setException(throwable); - - synchronized (seenExceptionsLock) { - if (seenExceptions == null) { - seenExceptions = Sets.newHashSet(); - } - firstTimeSeeingThisException = seenExceptions.add(throwable); - } - } - - if (throwable instanceof Error - || (allMustSucceed && !visibleFromOutputFuture && firstTimeSeeingThisException)) { - logger.log(Level.SEVERE, "input future failed.", throwable); - } - } - - /** - * Sets the value at the given index to that of the given future. - */ - private void setOneValue(int index, Future future) { - List localValues = values; - // TODO(user): This check appears to be redundant since values is - // assigned null only after the future completes. However, values - // is not volatile so it may be possible for us to observe the changes - // to these two values in a different order... which I think is why - // we need to check both. Clear up this craziness either by making - // values volatile or proving that it doesn't need to be for some other - // reason. - if (isDone() || localValues == null) { - // Some other future failed or has been cancelled, causing this one to - // also be cancelled or have an exception set. This should only happen - // if allMustSucceed is true or if the output itself has been - // cancelled. - checkState(allMustSucceed || isCancelled(), - "Future was done before all dependencies completed"); - } - - try { - checkState(future.isDone(), - "Tried to set value from future which is not done"); - V returnValue = getUninterruptibly(future); - if (localValues != null) { - localValues.set(index, returnValue); - } - } catch (CancellationException e) { - if (allMustSucceed) { - // Set ourselves as cancelled. Let the input futures keep running - // as some of them may be used elsewhere. - cancel(false); - } - } catch (ExecutionException e) { - setExceptionAndMaybeLog(e.getCause()); - } catch (Throwable t) { - setExceptionAndMaybeLog(t); - } finally { - int newRemaining = remaining.decrementAndGet(); - checkState(newRemaining >= 0, "Less than 0 remaining futures"); - if (newRemaining == 0) { -// FutureCombiner localCombiner = combiner; - if (/* localCombiner != null && */ localValues != null) { - set(localValues); - } else { - checkState(isDone(), "Future is not done"); - } - } - } - } - - } - - /** Used for {@link #allAsList} and {@link #successfulAsList}. */ - private static ListenableFuture> listFuture( - ImmutableList> futures, - boolean allMustSucceed, Executor listenerExecutor) { - return new CombinedFuture( - futures, allMustSucceed, listenerExecutor); -// new FutureCombiner>() { -// @Override -// public List combine(List values) { -//// List result = Lists.newArrayList(); -//// for (V element : values) { -//// result.add(element); -//// } -// return Collections.unmodifiableList(values); -// } -// }); - } - - /** - * A checked future that uses a function to map from exceptions to the - * appropriate checked type. - */ -// private static class MappingCheckedFuture extends -// AbstractCheckedFuture { -// -// final Function mapper; -// -// MappingCheckedFuture(ListenableFuture delegate, -// Function mapper) { -// super(delegate); -// -// this.mapper = checkNotNull(mapper); -// } -// -// @Override -// protected X mapException(Exception e) { -// return mapper.apply(e); -// } -// } - private static void checkState(boolean expression, String errorMessage) { - if (!expression) { - throw new IllegalStateException(errorMessage); - } - } -} diff --git a/java/src/game/future/ListenableFuture.java b/java/src/game/future/ListenableFuture.java deleted file mode 100644 index fcdec96..0000000 --- a/java/src/game/future/ListenableFuture.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -import java.util.concurrent.Executor; -import java.util.concurrent.Future; - -/** - * A {@link Future} that accepts completion listeners. Each listener has an - * associated executor, and it is invoked using this executor once the future's - * computation is {@linkplain Future#isDone() complete}. If the computation has - * already completed when the listener is added, the listener will execute - * immediately. - * - *

See the Guava User Guide article on - * {@code ListenableFuture}. - * - *

Purpose

- * - *

Most commonly, {@code ListenableFuture} is used as an input to another - * derived {@code Future}, as in {@link Futures#allAsList(Iterable) - * Futures.allAsList}. Many such methods are impossible to implement efficiently - * without listener support. - * - *

It is possible to call {@link #addListener addListener} directly, but this - * is uncommon because the {@code Runnable} interface does not provide direct - * access to the {@code Future} result. (Users who want such access may prefer - * {@link Futures#addCallback Futures.addCallback}.) Still, direct {@code - * addListener} calls are occasionally useful:

   {@code
- *   final String name = ...;
- *   inFlight.add(name);
- *   ListenableFuture future = service.query(name);
- *   future.addListener(new Runnable() {
- *     public void run() {
- *       processedCount.incrementAndGet();
- *       inFlight.remove(name);
- *       lastProcessed.set(name);
- *       logger.info("Done with {0}", name);
- *     }
- *   }, executor);}
- * - *

How to get an instance

- * - *

Developers are encouraged to return {@code ListenableFuture} from their - * methods so that users can take advantages of the utilities built atop the - * class. The way that they will create {@code ListenableFuture} instances - * depends on how they currently create {@code Future} instances: - *

    - *
  • If they are returned from an {@code ExecutorService}, convert that - * service to a {@link ListeningExecutorService}, usually by calling {@link - * MoreExecutors#listeningDecorator(ExecutorService) - * MoreExecutors.listeningDecorator}. (Custom executors may find it more - * convenient to use {@link ListenableFutureTask} directly.) - *
  • If they are manually filled in by a call to {@link FutureTask#set} or a - * similar method, create a {@link SettableFuture} instead. (Users with more - * complex needs may prefer {@link AbstractFuture}.) - *
- * - *

Occasionally, an API will return a plain {@code Future} and it will be - * impossible to change the return type. For this case, we provide a more - * expensive workaround in {@code JdkFutureAdapters}. However, when possible, it - * is more efficient and reliable to create a {@code ListenableFuture} directly. - * - * @author Sven Mawson - * @author Nishant Thakkar - * @since 1.0 - */ -public interface ListenableFuture extends Future { - /** - * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on - * the given executor. The listener will run when the {@code Future}'s - * computation is {@linkplain Future#isDone() complete} or, if the computation - * is already complete, immediately. - * - *

There is no guaranteed ordering of execution of listeners, but any - * listener added through this method is guaranteed to be called once the - * computation is complete. - * - *

Exceptions thrown by a listener will be propagated up to the executor. - * Any exception thrown during {@code Executor.execute} (e.g., a {@code - * RejectedExecutionException} or an exception thrown by {@linkplain - * MoreExecutors#sameThreadExecutor inline execution}) will be caught and - * logged. - * - *

Note: For fast, lightweight listeners that would be safe to execute in - * any thread, consider {@link MoreExecutors#sameThreadExecutor}. For heavier - * listeners, {@code sameThreadExecutor()} carries some caveats. For - * example, the listener may run on an unpredictable or undesirable thread: - * - *

    - *
  • If this {@code Future} is done at the time {@code addListener} is - * called, {@code addListener} will execute the listener inline. - *
  • If this {@code Future} is not yet done, {@code addListener} will - * schedule the listener to be run by the thread that completes this {@code - * Future}, which may be an internal system thread such as an RPC network - * thread. - *
- * - *

Also note that, regardless of which thread executes the - * {@code sameThreadExecutor()} listener, all other registered but unexecuted - * listeners are prevented from running during its execution, even if those - * listeners are to run in other executors. - * - *

This is the most general listener interface. For common operations - * performed using listeners, see {@link - * com.google.common.util.concurrent.Futures}. For a simplified but general - * listener interface, see {@link - * com.google.common.util.concurrent.Futures#addCallback addCallback()}. - * - * @param listener the listener to run when the computation is complete - * @param executor the executor to run the listener in - * @throws NullPointerException if the executor or listener was null - * @throws RejectedExecutionException if we tried to execute the listener - * immediately but the executor rejected it. - */ - void addListener(Runnable listener, Executor executor); -} diff --git a/java/src/game/future/ListenableFutureTask.java b/java/src/game/future/ListenableFutureTask.java deleted file mode 100644 index 38b0621..0000000 --- a/java/src/game/future/ListenableFutureTask.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2008 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.FutureTask; - -/** - * A {@link FutureTask} that also implements the {@link ListenableFuture} - * interface. Unlike {@code FutureTask}, {@code ListenableFutureTask} does not - * provide an overrideable {@link FutureTask#done() done()} method. For similar - * functionality, call {@link #addListener}. - * - *

- * - * @author Sven Mawson - * @since 1.0 - */ -public class ListenableFutureTask extends FutureTask - implements ListenableFuture { - // TODO(cpovirk): explore ways of making ListenableFutureTask final. There are - // some valid reasons such as BoundedQueueExecutorService to allow extends but it - // would be nice to make it final to avoid unintended usage. - - // The execution list to hold our listeners. - private final ExecutionList executionList = new ExecutionList(); - - /** - * Creates a {@code ListenableFutureTask} that will upon running, execute the - * given {@code Callable}. - * - * @param callable the callable task - * @since 10.0 - */ - public static ListenableFutureTask create(Callable callable) { - return new ListenableFutureTask(callable); - } - - /** - * Creates a {@code ListenableFutureTask} that will upon running, execute the - * given {@code Runnable}, and arrange that {@code get} will return the - * given result on successful completion. - * - * @param runnable the runnable task - * @param result the result to return on successful completion. If you don't - * need a particular result, consider using constructions of the form: - * {@code ListenableFuture f = ListenableFutureTask.create(runnable, - * null)} - * @since 10.0 - */ - public static ListenableFutureTask create( - Runnable runnable, V result) { - return new ListenableFutureTask(runnable, result); - } - - ListenableFutureTask(Callable callable) { - super(callable); - } - - ListenableFutureTask(Runnable runnable, V result) { - super(runnable, result); - } - - @Override - public void addListener(Runnable listener, Executor exec) { - executionList.add(listener, exec); - } - - /** - * Internal implementation detail used to invoke the listeners. - */ - @Override - protected void done() { - executionList.execute(); - } -} diff --git a/java/src/game/future/MoreExecutors.java b/java/src/game/future/MoreExecutors.java deleted file mode 100644 index 5e3e49a..0000000 --- a/java/src/game/future/MoreExecutors.java +++ /dev/null @@ -1,889 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.AbstractExecutorService; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Factory and utility methods for {@link java.util.concurrent.Executor}, {@link - * ExecutorService}, and {@link ThreadFactory}. - * - * @author Eric Fellheimer - * @author Kyle Littlefield - * @author Justin Mahoney - * @since 3.0 - */ -final class MoreExecutors { - private MoreExecutors() {} - - /** - * Converts the given ThreadPoolExecutor into an ExecutorService that exits - * when the application is complete. It does so by using daemon threads and - * adding a shutdown hook to wait for their completion. - * - *

This is mainly for fixed thread pools. - * See {@link Executors#newFixedThreadPool(int)}. - * - * @param executor the executor to modify to make sure it exits when the - * application is finished - * @param terminationTimeout how long to wait for the executor to - * finish before terminating the JVM - * @param timeUnit unit of time for the time parameter - * @return an unmodifiable version of the input which will not hang the JVM - */ -// @Beta -// public static ExecutorService getExitingExecutorService( -// ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { -// return new Application() -// .getExitingExecutorService(executor, terminationTimeout, timeUnit); -// } - - /** - * Converts the given ScheduledThreadPoolExecutor into a - * ScheduledExecutorService that exits when the application is complete. It - * does so by using daemon threads and adding a shutdown hook to wait for - * their completion. - * - *

This is mainly for fixed thread pools. - * See {@link Executors#newScheduledThreadPool(int)}. - * - * @param executor the executor to modify to make sure it exits when the - * application is finished - * @param terminationTimeout how long to wait for the executor to - * finish before terminating the JVM - * @param timeUnit unit of time for the time parameter - * @return an unmodifiable version of the input which will not hang the JVM - */ -// @Beta -// public static ScheduledExecutorService getExitingScheduledExecutorService( -// ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { -// return new Application() -// .getExitingScheduledExecutorService(executor, terminationTimeout, timeUnit); -// } - - /** - * Add a shutdown hook to wait for thread completion in the given - * {@link ExecutorService service}. This is useful if the given service uses - * daemon threads, and we want to keep the JVM from exiting immediately on - * shutdown, instead giving these daemon threads a chance to terminate - * normally. - * @param service ExecutorService which uses daemon threads - * @param terminationTimeout how long to wait for the executor to finish - * before terminating the JVM - * @param timeUnit unit of time for the time parameter - */ -// @Beta -// public static void addDelayedShutdownHook( -// ExecutorService service, long terminationTimeout, TimeUnit timeUnit) { -// new Application() -// .addDelayedShutdownHook(service, terminationTimeout, timeUnit); -// } - - /** - * Converts the given ThreadPoolExecutor into an ExecutorService that exits - * when the application is complete. It does so by using daemon threads and - * adding a shutdown hook to wait for their completion. - * - *

This method waits 120 seconds before continuing with JVM termination, - * even if the executor has not finished its work. - * - *

This is mainly for fixed thread pools. - * See {@link Executors#newFixedThreadPool(int)}. - * - * @param executor the executor to modify to make sure it exits when the - * application is finished - * @return an unmodifiable version of the input which will not hang the JVM - */ -// @Beta -// public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) { -// return new Application().getExitingExecutorService(executor); -// } - - /** - * Converts the given ThreadPoolExecutor into a ScheduledExecutorService that - * exits when the application is complete. It does so by using daemon threads - * and adding a shutdown hook to wait for their completion. - * - *

This method waits 120 seconds before continuing with JVM termination, - * even if the executor has not finished its work. - * - *

This is mainly for fixed thread pools. - * See {@link Executors#newScheduledThreadPool(int)}. - * - * @param executor the executor to modify to make sure it exits when the - * application is finished - * @return an unmodifiable version of the input which will not hang the JVM - */ -// @Beta -// public static ScheduledExecutorService getExitingScheduledExecutorService( -// ScheduledThreadPoolExecutor executor) { -// return new Application().getExitingScheduledExecutorService(executor); -// } - - /** Represents the current application to register shutdown hooks. */ -// @VisibleForTesting static class Application { -// -// final ExecutorService getExitingExecutorService( -// ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { -// useDaemonThreadFactory(executor); -// ExecutorService service = Executors.unconfigurableExecutorService(executor); -// addDelayedShutdownHook(service, terminationTimeout, timeUnit); -// return service; -// } -// -// final ScheduledExecutorService getExitingScheduledExecutorService( -// ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { -// useDaemonThreadFactory(executor); -// ScheduledExecutorService service = Executors.unconfigurableScheduledExecutorService(executor); -// addDelayedShutdownHook(service, terminationTimeout, timeUnit); -// return service; -// } -// -// final void addDelayedShutdownHook( -// final ExecutorService service, final long terminationTimeout, final TimeUnit timeUnit) { -// checkNotNull(service); -// checkNotNull(timeUnit); -// addShutdownHook(MoreExecutors.newThread("DelayedShutdownHook-for-" + service, new Runnable() { -// @Override -// public void run() { -// try { -// // We'd like to log progress and failures that may arise in the -// // following code, but unfortunately the behavior of logging -// // is undefined in shutdown hooks. -// // This is because the logging code installs a shutdown hook of its -// // own. See Cleaner class inside {@link LogManager}. -// service.shutdown(); -// service.awaitTermination(terminationTimeout, timeUnit); -// } catch (InterruptedException ignored) { -// // We're shutting down anyway, so just ignore. -// } -// } -// })); -// } -// -// final ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) { -// return getExitingExecutorService(executor, 120, TimeUnit.SECONDS); -// } -// -// final ScheduledExecutorService getExitingScheduledExecutorService( -// ScheduledThreadPoolExecutor executor) { -// return getExitingScheduledExecutorService(executor, 120, TimeUnit.SECONDS); -// } -// -// @VisibleForTesting void addShutdownHook(Thread hook) { -// Runtime.getRuntime().addShutdownHook(hook); -// } -// } -// -// private static void useDaemonThreadFactory(ThreadPoolExecutor executor) { -// executor.setThreadFactory(new ThreadFactoryBuilder() -// .setDaemon(true) -// .setThreadFactory(executor.getThreadFactory()) -// .build()); -// } - - /** - * Creates an executor service that runs each task in the thread - * that invokes {@code execute/submit}, as in {@link CallerRunsPolicy} This - * applies both to individually submitted tasks and to collections of tasks - * submitted via {@code invokeAll} or {@code invokeAny}. In the latter case, - * tasks will run serially on the calling thread. Tasks are run to - * completion before a {@code Future} is returned to the caller (unless the - * executor has been shutdown). - * - *

Although all tasks are immediately executed in the thread that - * submitted the task, this {@code ExecutorService} imposes a small - * locking overhead on each task submission in order to implement shutdown - * and termination behavior. - * - *

The implementation deviates from the {@code ExecutorService} - * specification with regards to the {@code shutdownNow} method. First, - * "best-effort" with regards to canceling running tasks is implemented - * as "no-effort". No interrupts or other attempts are made to stop - * threads executing tasks. Second, the returned list will always be empty, - * as any submitted task is considered to have started execution. - * This applies also to tasks given to {@code invokeAll} or {@code invokeAny} - * which are pending serial execution, even the subset of the tasks that - * have not yet started execution. It is unclear from the - * {@code ExecutorService} specification if these should be included, and - * it's much easier to implement the interpretation that they not be. - * Finally, a call to {@code shutdown} or {@code shutdownNow} may result - * in concurrent calls to {@code invokeAll/invokeAny} throwing - * RejectedExecutionException, although a subset of the tasks may already - * have been executed. - * - * @since 10.0 (mostly source-compatible since 3.0) - */ - public static SameThreadExecutorService sameThreadExecutor() { - return new SameThreadExecutorService(); - } - - // See sameThreadExecutor javadoc for behavioral notes. - private static class SameThreadExecutorService - extends AbstractExecutorService implements ExecutorService { - /** - * Lock used whenever accessing the state variables - * (runningTasks, shutdown, terminationCondition) of the executor - */ - private final Lock lock = new ReentrantLock(); - - /** Signaled after the executor is shutdown and running tasks are done */ - private final Condition termination = lock.newCondition(); - - /* - * Conceptually, these two variables describe the executor being in - * one of three states: - * - Active: shutdown == false - * - Shutdown: runningTasks > 0 and shutdown == true - * - Terminated: runningTasks == 0 and shutdown == true - */ - private int runningTasks = 0; - private boolean shutdown = false; - - @Override - public void execute(Runnable command) { - startTask(); - try { - command.run(); - } finally { - endTask(); - } - } - - @Override - public boolean isShutdown() { - lock.lock(); - try { - return shutdown; - } finally { - lock.unlock(); - } - } - - @Override - public void shutdown() { - lock.lock(); - try { - shutdown = true; - } finally { - lock.unlock(); - } - } - - // See sameThreadExecutor javadoc for unusual behavior of this method. - @Override - public List shutdownNow() { - shutdown(); - return Collections.emptyList(); - } - - @Override - public boolean isTerminated() { - lock.lock(); - try { - return shutdown && runningTasks == 0; - } finally { - lock.unlock(); - } - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - long nanos = unit.toNanos(timeout); - lock.lock(); - try { - for (;;) { - if (isTerminated()) { - return true; - } else if (nanos <= 0) { - return false; - } else { - nanos = termination.awaitNanos(nanos); - } - } - } finally { - lock.unlock(); - } - } - - /** - * Checks if the executor has been shut down and increments the running - * task count. - * - * @throws RejectedExecutionException if the executor has been previously - * shutdown - */ - private void startTask() { - lock.lock(); - try { - if (isShutdown()) { - throw new RejectedExecutionException("Executor already shutdown"); - } - runningTasks++; - } finally { - lock.unlock(); - } - } - - /** - * Decrements the running task count. - */ - private void endTask() { - lock.lock(); - try { - runningTasks--; - if (isTerminated()) { - termination.signalAll(); - } - } finally { - lock.unlock(); - } - } - - @Override protected final ListenableFutureTask newTaskFor(Runnable runnable, T value) { - return ListenableFutureTask.create(runnable, value); - } - - @Override protected final ListenableFutureTask newTaskFor(Callable callable) { - return ListenableFutureTask.create(callable); - } - - @Override public ListenableFuture submit(Runnable task) { - return (ListenableFuture) super.submit(task); - } - - @Override public ListenableFuture submit(Runnable task, T result) { - return (ListenableFuture) super.submit(task, result); - } - - @Override public ListenableFuture submit(Callable task) { - return (ListenableFuture) super.submit(task); - } - } - - /** - * Creates an {@link ExecutorService} whose {@code submit} and {@code - * invokeAll} methods submit {@link ListenableFutureTask} instances to the - * given delegate executor. Those methods, as well as {@code execute} and - * {@code invokeAny}, are implemented in terms of calls to {@code - * delegate.execute}. All other methods are forwarded unchanged to the - * delegate. This implies that the returned {@code ListeningExecutorService} - * never calls the delegate's {@code submit}, {@code invokeAll}, and {@code - * invokeAny} methods, so any special handling of tasks must be implemented in - * the delegate's {@code execute} method or by wrapping the returned {@code - * ListeningExecutorService}. - * - *

If the delegate executor was already an instance of {@code - * ListeningExecutorService}, it is returned untouched, and the rest of this - * documentation does not apply. - * - * @since 10.0 - */ -// public static ListeningExecutorService listeningDecorator( -// ExecutorService delegate) { -// return (delegate instanceof ListeningExecutorService) -// ? (ListeningExecutorService) delegate -// : (delegate instanceof ScheduledExecutorService) -// ? new ScheduledListeningDecorator((ScheduledExecutorService) delegate) -// : new ListeningDecorator(delegate); -// } - - /** - * Creates a {@link ScheduledExecutorService} whose {@code submit} and {@code - * invokeAll} methods submit {@link ListenableFutureTask} instances to the - * given delegate executor. Those methods, as well as {@code execute} and - * {@code invokeAny}, are implemented in terms of calls to {@code - * delegate.execute}. All other methods are forwarded unchanged to the - * delegate. This implies that the returned {@code - * ListeningScheduledExecutorService} never calls the delegate's {@code - * submit}, {@code invokeAll}, and {@code invokeAny} methods, so any special - * handling of tasks must be implemented in the delegate's {@code execute} - * method or by wrapping the returned {@code - * ListeningScheduledExecutorService}. - * - *

If the delegate executor was already an instance of {@code - * ListeningScheduledExecutorService}, it is returned untouched, and the rest - * of this documentation does not apply. - * - * @since 10.0 - */ -// public static ListeningScheduledExecutorService listeningDecorator( -// ScheduledExecutorService delegate) { -// return (delegate instanceof ListeningScheduledExecutorService) -// ? (ListeningScheduledExecutorService) delegate -// : new ScheduledListeningDecorator(delegate); -// } - -// private static class ListeningDecorator -// extends AbstractListeningExecutorService { -// private final ExecutorService delegate; -// -// ListeningDecorator(ExecutorService delegate) { -// this.delegate = checkNotNull(delegate); -// } -// -// @Override -// public boolean awaitTermination(long timeout, TimeUnit unit) -// throws InterruptedException { -// return delegate.awaitTermination(timeout, unit); -// } -// -// @Override -// public boolean isShutdown() { -// return delegate.isShutdown(); -// } -// -// @Override -// public boolean isTerminated() { -// return delegate.isTerminated(); -// } -// -// @Override -// public void shutdown() { -// delegate.shutdown(); -// } -// -// @Override -// public List shutdownNow() { -// return delegate.shutdownNow(); -// } -// -// @Override -// public void execute(Runnable command) { -// delegate.execute(command); -// } -// } -// -// private static class ScheduledListeningDecorator -// extends ListeningDecorator implements ListeningScheduledExecutorService { -// -// final ScheduledExecutorService delegate; -// -// ScheduledListeningDecorator(ScheduledExecutorService delegate) { -// super(delegate); -// this.delegate = checkNotNull(delegate); -// } -// -// @Override -// public ListenableScheduledFuture schedule( -// Runnable command, long delay, TimeUnit unit) { -// ListenableFutureTask task = -// ListenableFutureTask.create(command, null); -// ScheduledFuture scheduled = delegate.schedule(task, delay, unit); -// return new ListenableScheduledTask(task, scheduled); -// } -// -// @Override -// public ListenableScheduledFuture schedule( -// Callable callable, long delay, TimeUnit unit) { -// ListenableFutureTask task = ListenableFutureTask.create(callable); -// ScheduledFuture scheduled = delegate.schedule(task, delay, unit); -// return new ListenableScheduledTask(task, scheduled); -// } -// -// @Override -// public ListenableScheduledFuture scheduleAtFixedRate( -// Runnable command, long initialDelay, long period, TimeUnit unit) { -// NeverSuccessfulListenableFutureTask task = -// new NeverSuccessfulListenableFutureTask(command); -// ScheduledFuture scheduled = -// delegate.scheduleAtFixedRate(task, initialDelay, period, unit); -// return new ListenableScheduledTask(task, scheduled); -// } -// -// @Override -// public ListenableScheduledFuture scheduleWithFixedDelay( -// Runnable command, long initialDelay, long delay, TimeUnit unit) { -// NeverSuccessfulListenableFutureTask task = -// new NeverSuccessfulListenableFutureTask(command); -// ScheduledFuture scheduled = -// delegate.scheduleWithFixedDelay(task, initialDelay, delay, unit); -// return new ListenableScheduledTask(task, scheduled); -// } -// -// private static final class ListenableScheduledTask -// extends SimpleForwardingListenableFuture -// implements ListenableScheduledFuture { -// -// private final ScheduledFuture scheduledDelegate; -// -// public ListenableScheduledTask( -// ListenableFuture listenableDelegate, -// ScheduledFuture scheduledDelegate) { -// super(listenableDelegate); -// this.scheduledDelegate = scheduledDelegate; -// } -// -// @Override -// public boolean cancel(boolean mayInterruptIfRunning) { -// boolean cancelled = super.cancel(mayInterruptIfRunning); -// if (cancelled) { -// // Unless it is cancelled, the delegate may continue being scheduled -// scheduledDelegate.cancel(mayInterruptIfRunning); -// -// // TODO(user): Cancel "this" if "scheduledDelegate" is cancelled. -// } -// return cancelled; -// } -// -// @Override -// public long getDelay(TimeUnit unit) { -// return scheduledDelegate.getDelay(unit); -// } -// -// @Override -// public int compareTo(Delayed other) { -// return scheduledDelegate.compareTo(other); -// } -// } -// -// private static final class NeverSuccessfulListenableFutureTask -// extends AbstractFuture -// implements Runnable { -// private final Runnable delegate; -// -// public NeverSuccessfulListenableFutureTask(Runnable delegate) { -// this.delegate = checkNotNull(delegate); -// } -// -// @Override public void run() { -// try { -// delegate.run(); -// } catch (Throwable t) { -// setException(t); -// throw Throwables.propagate(t); -// } -// } -// } -// } - - /* - * This following method is a modified version of one found in - * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck/AbstractExecutorServiceTest.java?revision=1.30 - * which contained the following notice: - * - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - * Other contributors include Andrew Wright, Jeffrey Hayes, - * Pat Fisher, Mike Judd. - */ - - /** - * An implementation of {@link ExecutorService#invokeAny} for {@link ListeningExecutorService} - * implementations. - */ // static T invokeAnyImpl(ListeningExecutorService executorService, -// Collection> tasks, boolean timed, long nanos) -// throws InterruptedException, ExecutionException, TimeoutException { -// checkNotNull(executorService); -// int ntasks = tasks.size(); -// checkArgument(ntasks > 0); -// List> futures = Lists.newArrayListWithCapacity(ntasks); -// BlockingQueue> futureQueue = Queues.newLinkedBlockingQueue(); -// -// // For efficiency, especially in executors with limited -// // parallelism, check to see if previously submitted tasks are -// // done before submitting more of them. This interleaving -// // plus the exception mechanics account for messiness of main -// // loop. -// -// try { -// // Record exceptions so that if we fail to obtain any -// // result, we can throw the last exception we got. -// ExecutionException ee = null; -// long lastTime = timed ? System.nanoTime() : 0; -// Iterator> it = tasks.iterator(); -// -// futures.add(submitAndAddQueueListener(executorService, it.next(), futureQueue)); -// --ntasks; -// int active = 1; -// -// for (;;) { -// Future f = futureQueue.poll(); -// if (f == null) { -// if (ntasks > 0) { -// --ntasks; -// futures.add(submitAndAddQueueListener(executorService, it.next(), futureQueue)); -// ++active; -// } else if (active == 0) { -// break; -// } else if (timed) { -// f = futureQueue.poll(nanos, TimeUnit.NANOSECONDS); -// if (f == null) { -// throw new TimeoutException(); -// } -// long now = System.nanoTime(); -// nanos -= now - lastTime; -// lastTime = now; -// } else { -// f = futureQueue.take(); -// } -// } -// if (f != null) { -// --active; -// try { -// return f.get(); -// } catch (ExecutionException eex) { -// ee = eex; -// } catch (RuntimeException rex) { -// ee = new ExecutionException(rex); -// } -// } -// } -// -// if (ee == null) { -// ee = new ExecutionException(null); -// } -// throw ee; -// } finally { -// for (Future f : futures) { -// f.cancel(true); -// } -// } -// } - - /** - * Submits the task and adds a listener that adds the future to {@code queue} when it completes. - */ -// private static ListenableFuture submitAndAddQueueListener( -// ListeningExecutorService executorService, Callable task, -// final BlockingQueue> queue) { -// final ListenableFuture future = executorService.submit(task); -// future.addListener(new Runnable() { -// @Override public void run() { -// queue.add(future); -// } -// }, MoreExecutors.sameThreadExecutor()); -// return future; -// } - - /** - * Returns a default thread factory used to create new threads. - * - *

On AppEngine, returns {@code ThreadManager.currentRequestThreadFactory()}. - * Otherwise, returns {@link Executors#defaultThreadFactory()}. - * - * @since 14.0 - */ -// @Beta -// public static ThreadFactory platformThreadFactory() { -// if (!isAppEngine()) { -// return Executors.defaultThreadFactory(); -// } -// try { -// return (ThreadFactory) Class.forName("com.google.appengine.api.ThreadManager") -// .getMethod("currentRequestThreadFactory") -// .invoke(null); -// } catch (IllegalAccessException e) { -// throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); -// } catch (ClassNotFoundException e) { -// throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); -// } catch (NoSuchMethodException e) { -// throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); -// } catch (InvocationTargetException e) { -// throw Throwables.propagate(e.getCause()); -// } -// } - -// private static boolean isAppEngine() { -// if (System.getProperty("com.google.appengine.runtime.environment") == null) { -// return false; -// } -// try { -// // If the current environment is null, we're not inside AppEngine. -// return Class.forName("com.google.apphosting.api.ApiProxy") -// .getMethod("getCurrentEnvironment") -// .invoke(null) != null; -// } catch (ClassNotFoundException e) { -// // If ApiProxy doesn't exist, we're not on AppEngine at all. -// return false; -// } catch (InvocationTargetException e) { -// // If ApiProxy throws an exception, we're not in a proper AppEngine environment. -// return false; -// } catch (IllegalAccessException e) { -// // If the method isn't accessible, we're not on a supported version of AppEngine; -// return false; -// } catch (NoSuchMethodException e) { -// // If the method doesn't exist, we're not on a supported version of AppEngine; -// return false; -// } -// } - - /** - * Creates a thread using {@link #platformThreadFactory}, and sets its name to {@code name} - * unless changing the name is forbidden by the security manager. - */ -// static Thread newThread(String name, Runnable runnable) { -// checkNotNull(name); -// checkNotNull(runnable); -// Thread result = platformThreadFactory().newThread(runnable); -// try { -// result.setName(name); -// } catch (SecurityException e) { -// // OK if we can't set the name in this environment. -// } -// return result; -// } - - // TODO(user): provide overloads for ListeningExecutorService? ListeningScheduledExecutorService? - // TODO(user): provide overloads that take constant strings? Functions to - // calculate names? - - /** - * Creates an {@link Executor} that renames the {@link Thread threads} that its tasks run in. - * - *

The names are retrieved from the {@code nameSupplier} on the thread that is being renamed - * right before each task is run. The renaming is best effort, if a {@link SecurityManager} - * prevents the renaming then it will be skipped but the tasks will still execute. - * - * - * @param executor The executor to decorate - * @param nameSupplier The source of names for each task - */ -// static Executor renamingDecorator(final Executor executor, final Supplier nameSupplier) { -// checkNotNull(executor); -// checkNotNull(nameSupplier); -// if (isAppEngine()) { -// // AppEngine doesn't support thread renaming, so don't even try -// return executor; -// } -// return new Executor() { -// @Override public void execute(Runnable command) { -// executor.execute(Callables.threadRenaming(command, nameSupplier)); -// } -// }; -// } - - /** - * Creates an {@link ExecutorService} that renames the {@link Thread threads} that its tasks run - * in. - * - *

The names are retrieved from the {@code nameSupplier} on the thread that is being renamed - * right before each task is run. The renaming is best effort, if a {@link SecurityManager} - * prevents the renaming then it will be skipped but the tasks will still execute. - * - * - * @param service The executor to decorate - * @param nameSupplier The source of names for each task - */ -// static ExecutorService renamingDecorator(final ExecutorService service, -// final Supplier nameSupplier) { -// checkNotNull(service); -// checkNotNull(nameSupplier); -// if (isAppEngine()) { -// // AppEngine doesn't support thread renaming, so don't even try. -// return service; -// } -// return new WrappingExecutorService(service) { -// @Override protected Callable wrapTask(Callable callable) { -// return Callables.threadRenaming(callable, nameSupplier); -// } -// @Override protected Runnable wrapTask(Runnable command) { -// return Callables.threadRenaming(command, nameSupplier); -// } -// }; -// } - - /** - * Creates a {@link ScheduledExecutorService} that renames the {@link Thread threads} that its - * tasks run in. - * - *

The names are retrieved from the {@code nameSupplier} on the thread that is being renamed - * right before each task is run. The renaming is best effort, if a {@link SecurityManager} - * prevents the renaming then it will be skipped but the tasks will still execute. - * - * - * @param service The executor to decorate - * @param nameSupplier The source of names for each task - */ -// static ScheduledExecutorService renamingDecorator(final ScheduledExecutorService service, -// final Supplier nameSupplier) { -// checkNotNull(service); -// checkNotNull(nameSupplier); -// if (isAppEngine()) { -// // AppEngine doesn't support thread renaming, so don't even try. -// return service; -// } -// return new WrappingScheduledExecutorService(service) { -// @Override protected Callable wrapTask(Callable callable) { -// return Callables.threadRenaming(callable, nameSupplier); -// } -// @Override protected Runnable wrapTask(Runnable command) { -// return Callables.threadRenaming(command, nameSupplier); -// } -// }; -// } - - /** - * Shuts down the given executor gradually, first disabling new submissions and later cancelling - * existing tasks. - * - *

The method takes the following steps: - *

    - *
  1. calls {@link ExecutorService#shutdown()}, disabling acceptance of new submitted tasks. - *
  2. waits for half of the specified timeout. - *
  3. if the timeout expires, it calls {@link ExecutorService#shutdownNow()}, cancelling - * pending tasks and interrupting running tasks. - *
  4. waits for the other half of the specified timeout. - *
- * - *

If, at any step of the process, the given executor is terminated or the calling thread is - * interrupted, the method may return without executing any remaining steps. - * - * @param service the {@code ExecutorService} to shut down - * @param timeout the maximum time to wait for the {@code ExecutorService} to terminate - * @param unit the time unit of the timeout argument - * @return {@code true) if the pool was terminated successfully, {@code false} if the - * {@code ExecutorService} could not terminate or the thread running this method - * is interrupted while waiting for the {@code ExecutorService} to terminate - * @since 17.0 - */ -// @Beta -// public static boolean shutdownAndAwaitTermination( -// ExecutorService service, long timeout, TimeUnit unit) { -// checkNotNull(unit); -// // Disable new tasks from being submitted -// service.shutdown(); -// try { -// long halfTimeoutNanos = TimeUnit.NANOSECONDS.convert(timeout, unit) / 2; -// // Wait for half the duration of the timeout for existing tasks to terminate -// if (!service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS)) { -// // Cancel currently executing tasks -// service.shutdownNow(); -// // Wait the other half of the timeout for tasks to respond to being cancelled -// service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS); -// } -// } catch (InterruptedException ie) { -// // Preserve interrupt status -// Thread.currentThread().interrupt(); -// // (Re-)Cancel if current thread also interrupted -// service.shutdownNow(); -// } -// return service.isTerminated(); -// } -} diff --git a/java/src/game/future/ThreadFactoryBuilder.java b/java/src/game/future/ThreadFactoryBuilder.java deleted file mode 100644 index 611bdf0..0000000 --- a/java/src/game/future/ThreadFactoryBuilder.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2010 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicLong; - -/** - * A ThreadFactory builder, providing any combination of these features: - *

    - *
  • whether threads should be marked as {@linkplain Thread#setDaemon daemon} - * threads - *
  • a {@linkplain ThreadFactoryBuilder#setNameFormat naming format} - *
  • a {@linkplain Thread#setPriority thread priority} - *
  • an {@linkplain Thread#setUncaughtExceptionHandler uncaught exception - * handler} - *
  • a {@linkplain ThreadFactory#newThread backing thread factory} - *
- *

If no backing thread factory is provided, a default backing thread factory is - * used as if by calling {@code setThreadFactory(}{@link - * Executors#defaultThreadFactory()}{@code )}. - * - * @author Kurt Alfred Kluever - * @since 4.0 - */ -public final class ThreadFactoryBuilder { - private String nameFormat = null; - private Boolean daemon = null; - private Integer priority = null; - private UncaughtExceptionHandler uncaughtExceptionHandler = null; - private ThreadFactory backingThreadFactory = null; - - /** - * Creates a new {@link ThreadFactory} builder. - */ - public ThreadFactoryBuilder() {} - - /** - * Sets the naming format to use when naming threads ({@link Thread#setName}) - * which are created with this ThreadFactory. - * - * @param nameFormat a {@link String#format(String, Object...)}-compatible - * format String, to which a unique integer (0, 1, etc.) will be supplied - * as the single parameter. This integer will be unique to the built - * instance of the ThreadFactory and will be assigned sequentially. For - * example, {@code "rpc-pool-%d"} will generate thread names like - * {@code "rpc-pool-0"}, {@code "rpc-pool-1"}, {@code "rpc-pool-2"}, etc. - * @return this for the builder pattern - */ - - public ThreadFactoryBuilder setNameFormat(String nameFormat) { - String.format(nameFormat, 0); // fail fast if the format is bad or null - this.nameFormat = nameFormat; - return this; - } - - /** - * Sets daemon or not for new threads created with this ThreadFactory. - * - * @param daemon whether or not new Threads created with this ThreadFactory - * will be daemon threads - * @return this for the builder pattern - */ - public ThreadFactoryBuilder setDaemon(boolean daemon) { - this.daemon = daemon; - return this; - } - - /** - * Sets the priority for new threads created with this ThreadFactory. - * - * @param priority the priority for new Threads created with this - * ThreadFactory - * @return this for the builder pattern - */ -// public ThreadFactoryBuilder setPriority(int priority) { - // Thread#setPriority() already checks for validity. These error messages - // are nicer though and will fail-fast. -// checkArgument(priority >= Thread.MIN_PRIORITY, -// "Thread priority (%s) must be >= %s", priority, Thread.MIN_PRIORITY); -// checkArgument(priority <= Thread.MAX_PRIORITY, -// "Thread priority (%s) must be <= %s", priority, Thread.MAX_PRIORITY); -// this.priority = priority; -// return this; -// } - - /** - * Sets the {@link UncaughtExceptionHandler} for new threads created with this - * ThreadFactory. - * - * @param uncaughtExceptionHandler the uncaught exception handler for new - * Threads created with this ThreadFactory - * @return this for the builder pattern - */ -// public ThreadFactoryBuilder setUncaughtExceptionHandler( -// UncaughtExceptionHandler uncaughtExceptionHandler) { -// this.uncaughtExceptionHandler = checkNotNull(uncaughtExceptionHandler); -// return this; -// } - - /** - * Sets the backing {@link ThreadFactory} for new threads created with this - * ThreadFactory. Threads will be created by invoking #newThread(Runnable) on - * this backing {@link ThreadFactory}. - * - * @param backingThreadFactory the backing {@link ThreadFactory} which will - * be delegated to during thread creation. - * @return this for the builder pattern - * - * @see MoreExecutors - */ -// public ThreadFactoryBuilder setThreadFactory( -// ThreadFactory backingThreadFactory) { -// this.backingThreadFactory = checkNotNull(backingThreadFactory); -// return this; -// } - - /** - * Returns a new thread factory using the options supplied during the building - * process. After building, it is still possible to change the options used to - * build the ThreadFactory and/or build again. State is not shared amongst - * built instances. - * - * @return the fully constructed {@link ThreadFactory} - */ - public ThreadFactory build() { - return build(this); - } - - private static ThreadFactory build(ThreadFactoryBuilder builder) { - final String nameFormat = builder.nameFormat; - final Boolean daemon = builder.daemon; - final Integer priority = builder.priority; - final UncaughtExceptionHandler uncaughtExceptionHandler = - builder.uncaughtExceptionHandler; - final ThreadFactory backingThreadFactory = - (builder.backingThreadFactory != null) - ? builder.backingThreadFactory - : Executors.defaultThreadFactory(); - final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null; - return new ThreadFactory() { - @Override public Thread newThread(Runnable runnable) { - Thread thread = backingThreadFactory.newThread(runnable); - if (nameFormat != null) { - thread.setName(String.format(nameFormat, count.getAndIncrement())); - } - if (daemon != null) { - thread.setDaemon(daemon); - } - if (priority != null) { - thread.setPriority(priority); - } - if (uncaughtExceptionHandler != null) { - thread.setUncaughtExceptionHandler(uncaughtExceptionHandler); - } - return thread; - } - }; - } -} diff --git a/java/src/game/future/UncheckedExecutionException.java b/java/src/game/future/UncheckedExecutionException.java deleted file mode 100644 index 4f25bf8..0000000 --- a/java/src/game/future/UncheckedExecutionException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2011 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.future; - -/** - * Unchecked variant of {@link java.util.concurrent.ExecutionException}. As with - * {@code ExecutionException}, the exception's {@linkplain #getCause() cause} - * comes from a failed task, possibly run in another thread. - * - *

{@code UncheckedExecutionException} is intended as an alternative to - * {@code ExecutionException} when the exception thrown by a task is an - * unchecked exception. However, it may also wrap a checked exception in some - * cases. - * - *

When wrapping an {@code Error} from another thread, prefer {@link - * ExecutionError}. When wrapping a checked exception, prefer {@code - * ExecutionException}. - * - * @author Charles Fry - * @since 10.0 - */ - -class UncheckedExecutionException extends RuntimeException { - /** - * Creates a new instance with {@code null} as its detail message. - */ - protected UncheckedExecutionException() {} - - /** - * Creates a new instance with the given detail message. - */ - protected UncheckedExecutionException(String message) { - super(message); - } - - /** - * Creates a new instance with the given detail message and cause. - */ - public UncheckedExecutionException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance with the given cause. - */ - public UncheckedExecutionException(Throwable cause) { - super(cause); - } - - private static final long serialVersionUID = 0; -} diff --git a/java/src/game/gui/Gui.java b/java/src/game/gui/Gui.java index b535784..fadcef7 100644 --- a/java/src/game/gui/Gui.java +++ b/java/src/game/gui/Gui.java @@ -2,8 +2,9 @@ package game.gui; import java.util.List; +import com.google.common.collect.Lists; + import game.Game; -import game.collect.Lists; import game.gui.element.Dropdown; import game.gui.element.Element; import game.gui.element.Dropdown.Handle; diff --git a/java/src/game/gui/GuiConsole.java b/java/src/game/gui/GuiConsole.java index 2ab9c10..595b641 100644 --- a/java/src/game/gui/GuiConsole.java +++ b/java/src/game/gui/GuiConsole.java @@ -2,7 +2,8 @@ package game.gui; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.gui.element.ActButton; import game.gui.element.Fill; import game.gui.element.Textbox; diff --git a/java/src/game/gui/GuiInfo.java b/java/src/game/gui/GuiInfo.java index 973033e..3678b79 100644 --- a/java/src/game/gui/GuiInfo.java +++ b/java/src/game/gui/GuiInfo.java @@ -17,8 +17,8 @@ public class GuiInfo extends Gui { "\n" + TextColor.YELLOW + "Verwendete Programmbibliotheken:" + "\n" + TextColor.LGRAY + " -> " + TextColor.NEON + "LWJGL 3.3.6+1 (GLFW + OpenGL)" + "\n" + - TextColor.LGRAY + " -> " + TextColor.NEON + "nionet (Modifiziert: Netty 4.0.23-Final)" + "\n" + - TextColor.LGRAY + " -> " + TextColor.NEON + "collectutil + futureutil (Modifiziert: Guava 17.0)" + "\n" + + TextColor.LGRAY + " -> " + TextColor.NEON + "Netty 4.1.119-Final" + "\n" + + TextColor.LGRAY + " -> " + TextColor.NEON + "Guava 33.4.0" + "\n" + TextColor.LGRAY + " -> " + TextColor.NEON + "tjglu (Modifiziert: LWJGL 2.9.4-nightly-20150209)" + "\n" + // "\n" + // TextColor.YELLOW + "Verwendeter Compiler: " + "\n" + diff --git a/java/src/game/gui/container/GuiContainer.java b/java/src/game/gui/container/GuiContainer.java index eec09ff..1754c1f 100755 --- a/java/src/game/gui/container/GuiContainer.java +++ b/java/src/game/gui/container/GuiContainer.java @@ -3,8 +3,9 @@ package game.gui.container; import java.util.List; import java.util.Set; -import game.collect.Lists; -import game.collect.Sets; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + import game.color.TextColor; import game.gui.Gui; import game.gui.element.InventoryButton; diff --git a/java/src/game/gui/element/GuiList.java b/java/src/game/gui/element/GuiList.java index 78646c5..f6181a4 100755 --- a/java/src/game/gui/element/GuiList.java +++ b/java/src/game/gui/element/GuiList.java @@ -2,7 +2,8 @@ package game.gui.element; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.gui.Gui; import game.renderer.DefaultVertexFormats; import game.renderer.Drawing; diff --git a/java/src/game/gui/world/GuiWorlds.java b/java/src/game/gui/world/GuiWorlds.java index ba13c72..0bf90e2 100755 --- a/java/src/game/gui/world/GuiWorlds.java +++ b/java/src/game/gui/world/GuiWorlds.java @@ -10,7 +10,8 @@ import java.util.Collections; import java.util.Date; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; + import game.color.TextColor; import game.dimension.Dimension; import game.gui.GuiConfirm; diff --git a/java/src/game/init/CraftingRegistry.java b/java/src/game/init/CraftingRegistry.java index e7f08f2..c3cbcd7 100755 --- a/java/src/game/init/CraftingRegistry.java +++ b/java/src/game/init/CraftingRegistry.java @@ -6,6 +6,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.Block; import game.block.BlockBed; import game.block.BlockDirt; @@ -16,8 +19,6 @@ import game.block.BlockSand; import game.block.BlockSandStone; import game.block.BlockStoneBrick; import game.block.BlockWall; -import game.collect.Lists; -import game.collect.Maps; import game.color.DyeColor; import game.entity.animal.EntitySheep; import game.inventory.InventoryCrafting; diff --git a/java/src/game/init/EntityRegistry.java b/java/src/game/init/EntityRegistry.java index 765d17b..4b9d6ed 100755 --- a/java/src/game/init/EntityRegistry.java +++ b/java/src/game/init/EntityRegistry.java @@ -3,7 +3,8 @@ package game.init; import java.util.Map; import java.util.Set; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.entity.Entity; import game.entity.animal.EntityBat; import game.entity.animal.EntityChicken; diff --git a/java/src/game/init/FluidRegistry.java b/java/src/game/init/FluidRegistry.java index 88545a9..d5433d5 100755 --- a/java/src/game/init/FluidRegistry.java +++ b/java/src/game/init/FluidRegistry.java @@ -3,12 +3,13 @@ package game.init; import java.util.List; import java.util.Map; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.Block; import game.block.BlockDynamicLiquid; import game.block.BlockLiquid; import game.block.BlockStaticLiquid; -import game.collect.Lists; -import game.collect.Maps; import game.material.Material; public abstract class FluidRegistry { diff --git a/java/src/game/init/ItemRegistry.java b/java/src/game/init/ItemRegistry.java index 28dc60f..b7a189b 100755 --- a/java/src/game/init/ItemRegistry.java +++ b/java/src/game/init/ItemRegistry.java @@ -4,6 +4,9 @@ import java.util.Map; import java.util.Set; import java.util.function.Function; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import game.block.Block; import game.block.BlockBed; import game.block.BlockButton; @@ -20,8 +23,6 @@ import game.block.BlockSapling; import game.block.BlockSlab; import game.block.BlockStoneBrick; import game.block.BlockWall; -import game.collect.Maps; -import game.collect.Sets; import game.color.DyeColor; import game.color.TextColor; import game.entity.item.EntityCart; diff --git a/java/src/game/init/ObjectIntIdentityMap.java b/java/src/game/init/ObjectIntIdentityMap.java index 42b0642..91a88d7 100755 --- a/java/src/game/init/ObjectIntIdentityMap.java +++ b/java/src/game/init/ObjectIntIdentityMap.java @@ -4,9 +4,9 @@ import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; -import game.collect.Iterators; -import game.collect.Lists; -import game.util.Predicates; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; public class ObjectIntIdentityMap implements IObjectIntIterable { diff --git a/java/src/game/init/RegistryNamespaced.java b/java/src/game/init/RegistryNamespaced.java index 0b48909..7a4a633 100755 --- a/java/src/game/init/RegistryNamespaced.java +++ b/java/src/game/init/RegistryNamespaced.java @@ -3,8 +3,8 @@ package game.init; import java.util.Iterator; import java.util.Map; -import game.collect.BiMap; -import game.collect.HashBiMap; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; public class RegistryNamespaced extends RegistrySimple implements IObjectIntIterable { diff --git a/java/src/game/init/RegistrySimple.java b/java/src/game/init/RegistrySimple.java index 5b41625..467902c 100755 --- a/java/src/game/init/RegistrySimple.java +++ b/java/src/game/init/RegistrySimple.java @@ -5,7 +5,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; -import game.collect.Maps; +import com.google.common.collect.Maps; public class RegistrySimple implements IRegistry { diff --git a/java/src/game/init/RotationRegistry.java b/java/src/game/init/RotationRegistry.java index e8b38ff..d04e766 100755 --- a/java/src/game/init/RotationRegistry.java +++ b/java/src/game/init/RotationRegistry.java @@ -3,7 +3,10 @@ package game.init; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import game.block.Block; import game.block.BlockDoor; @@ -19,8 +22,6 @@ import game.block.BlockRotatedPillar; import game.clipboard.Rotation; import game.clipboard.RotationValue; import game.clipboard.Vector; -import game.collect.Lists; -import game.collect.Maps; import game.properties.IProperty; import game.properties.PropertyDirection; import game.world.Facing; @@ -37,7 +38,7 @@ public abstract class RotationRegistry { if(prop == BlockDoor.FACING) { predicate = new Predicate() { @Override - public boolean test(Integer meta) { + public boolean apply(Integer meta) { return (meta & 8) == 0; } }; diff --git a/java/src/game/init/SmeltingRegistry.java b/java/src/game/init/SmeltingRegistry.java index 1d2e404..1ab21e1 100755 --- a/java/src/game/init/SmeltingRegistry.java +++ b/java/src/game/init/SmeltingRegistry.java @@ -2,11 +2,13 @@ package game.init; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Maps; + import java.util.Set; import game.block.Block; import game.block.BlockStoneBrick; -import game.collect.Maps; import game.color.DyeColor; import game.item.Item; import game.item.ItemFishFood; diff --git a/java/src/game/init/SpeciesRegistry.java b/java/src/game/init/SpeciesRegistry.java index c240089..b0ba646 100755 --- a/java/src/game/init/SpeciesRegistry.java +++ b/java/src/game/init/SpeciesRegistry.java @@ -4,9 +4,10 @@ import java.util.List; import java.util.Map; import java.util.Set; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import game.entity.npc.EntityArachnoid; import game.entity.npc.EntityBloodElf; import game.entity.npc.EntityChaosMarine; diff --git a/java/src/game/init/TileRegistry.java b/java/src/game/init/TileRegistry.java index 8da4f9d..1ce3a0e 100755 --- a/java/src/game/init/TileRegistry.java +++ b/java/src/game/init/TileRegistry.java @@ -2,7 +2,8 @@ package game.init; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.tileentity.TileEntity; import game.tileentity.TileEntityBanner; import game.tileentity.TileEntityBeacon; diff --git a/java/src/game/init/ToolMaterial.java b/java/src/game/init/ToolMaterial.java index 85fade6..6872aa5 100755 --- a/java/src/game/init/ToolMaterial.java +++ b/java/src/game/init/ToolMaterial.java @@ -2,7 +2,8 @@ package game.init; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; + import game.item.Item; public class ToolMaterial diff --git a/java/src/game/init/UniverseRegistry.java b/java/src/game/init/UniverseRegistry.java index 8d15e78..5170612 100755 --- a/java/src/game/init/UniverseRegistry.java +++ b/java/src/game/init/UniverseRegistry.java @@ -3,15 +3,17 @@ package game.init; import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import java.util.Set; import game.biome.Biome; import game.block.BlockColored; import game.block.BlockSand; import game.block.LeavesType; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; import game.color.DyeColor; import game.dimension.Area; import game.dimension.DimType; diff --git a/java/src/game/inventory/Container.java b/java/src/game/inventory/Container.java index ab0313c..230729c 100755 --- a/java/src/game/inventory/Container.java +++ b/java/src/game/inventory/Container.java @@ -3,8 +3,9 @@ package game.inventory; import java.util.List; import java.util.Set; -import game.collect.Lists; -import game.collect.Sets; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + import game.entity.npc.EntityNPC; import game.item.Item; import game.item.ItemStack; diff --git a/java/src/game/inventory/ContainerLocalMenu.java b/java/src/game/inventory/ContainerLocalMenu.java index 08d7992..058a42a 100755 --- a/java/src/game/inventory/ContainerLocalMenu.java +++ b/java/src/game/inventory/ContainerLocalMenu.java @@ -2,7 +2,8 @@ package game.inventory; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.entity.npc.EntityNPC; import game.tileentity.ILockableContainer; import game.tileentity.LockCode; diff --git a/java/src/game/inventory/ContainerPlayer.java b/java/src/game/inventory/ContainerPlayer.java index c5ce694..db973bd 100755 --- a/java/src/game/inventory/ContainerPlayer.java +++ b/java/src/game/inventory/ContainerPlayer.java @@ -2,7 +2,8 @@ package game.inventory; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.attributes.AttributeMap; import game.entity.npc.EntityNPC; import game.init.CraftingRegistry; diff --git a/java/src/game/inventory/InventoryBasic.java b/java/src/game/inventory/InventoryBasic.java index c7667da..a080a4f 100755 --- a/java/src/game/inventory/InventoryBasic.java +++ b/java/src/game/inventory/InventoryBasic.java @@ -2,7 +2,8 @@ package game.inventory; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.npc.EntityNPC; import game.item.ItemStack; diff --git a/java/src/game/item/Item.java b/java/src/game/item/Item.java index efd494a..ab26914 100755 --- a/java/src/game/item/Item.java +++ b/java/src/game/item/Item.java @@ -4,9 +4,10 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import game.block.Block; -import game.collect.Maps; -import game.collect.Sets; import game.color.TextColor; import game.entity.attributes.Attribute; import game.entity.attributes.AttributeModifier; diff --git a/java/src/game/item/ItemArmor.java b/java/src/game/item/ItemArmor.java index f204231..778c8ba 100755 --- a/java/src/game/item/ItemArmor.java +++ b/java/src/game/item/ItemArmor.java @@ -3,10 +3,11 @@ package game.item; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Sets; import game.block.BlockDispenser; -import game.collect.Sets; import game.dispenser.BehaviorDefaultDispenseItem; import game.dispenser.IBehaviorDispenseItem; import game.dispenser.IBlockSource; @@ -37,7 +38,7 @@ public class ItemArmor extends Item int k = blockpos.getZ(); BoundingBox axisalignedbb = new BoundingBox((double)i, (double)j, (double)k, (double)(i + 1), (double)(j + 1), (double)(k + 1)); List list = source.getWorld().getEntitiesWithinAABB(EntityLiving.class, axisalignedbb, new Predicate() { - public boolean test(EntityLiving entity) { + public boolean apply(EntityLiving entity) { return entity.isEntityAlive() && entity instanceof EntityNPC && entity.getItem(ItemArmor.getArmorPosition(stack)) != null; // || entitylivingbase.isPlayer()); } diff --git a/java/src/game/item/ItemBucket.java b/java/src/game/item/ItemBucket.java index ae14665..26f8482 100755 --- a/java/src/game/item/ItemBucket.java +++ b/java/src/game/item/ItemBucket.java @@ -7,11 +7,12 @@ import java.util.List; import java.util.Queue; import java.util.Set; +import com.google.common.collect.Sets; + import game.block.Block; import game.block.BlockDynamicLiquid; import game.block.BlockLiquid; import game.block.BlockStaticLiquid; -import game.collect.Sets; import game.entity.npc.EntityNPC; import game.init.BlockRegistry; import game.init.Blocks; diff --git a/java/src/game/item/ItemBucketMilk.java b/java/src/game/item/ItemBucketMilk.java index d6aea49..1829a1e 100755 --- a/java/src/game/item/ItemBucketMilk.java +++ b/java/src/game/item/ItemBucketMilk.java @@ -3,7 +3,8 @@ package game.item; import java.util.Map; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; + import game.entity.attributes.Attribute; import game.entity.attributes.AttributeModifier; import game.entity.attributes.Attributes; diff --git a/java/src/game/item/ItemFirework.java b/java/src/game/item/ItemFirework.java index 5f606c9..8dcd57c 100755 --- a/java/src/game/item/ItemFirework.java +++ b/java/src/game/item/ItemFirework.java @@ -2,7 +2,8 @@ package game.item; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.item.EntityFireworks; import game.entity.npc.EntityNPC; import game.nbt.NBTTagCompound; diff --git a/java/src/game/item/ItemFishFood.java b/java/src/game/item/ItemFishFood.java index baa16d4..65bfd37 100755 --- a/java/src/game/item/ItemFishFood.java +++ b/java/src/game/item/ItemFishFood.java @@ -3,7 +3,8 @@ package game.item; import java.util.List; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.entity.npc.EntityNPC; import game.potion.Potion; import game.potion.PotionEffect; diff --git a/java/src/game/item/ItemMagnet.java b/java/src/game/item/ItemMagnet.java index 45b63e2..92960ab 100755 --- a/java/src/game/item/ItemMagnet.java +++ b/java/src/game/item/ItemMagnet.java @@ -1,7 +1,7 @@ package game.item; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.entity.Entity; import game.entity.animal.EntityChicken; @@ -36,7 +36,7 @@ public class ItemMagnet extends Item { new BoundingBox(playerIn.posX - 40.0f, playerIn.posY + playerIn.getEyeHeight() - 40.0f, playerIn.posZ - 40.0f, playerIn.posX + 40.0f, playerIn.posY + playerIn.getEyeHeight() + 40.0f, playerIn.posZ + 40.0f), new Predicate() { - public boolean test(Entity entity) { + public boolean apply(Entity entity) { return (ItemMagnet.this.chicken || /* ? !((EntityLiving)entity).isAIDisabled() : */ entity.isMagnetic()) && entity.getDistanceToEntity(playerIn) <= 38.0f; } diff --git a/java/src/game/item/ItemMetal.java b/java/src/game/item/ItemMetal.java index 428ac93..70c484b 100755 --- a/java/src/game/item/ItemMetal.java +++ b/java/src/game/item/ItemMetal.java @@ -4,7 +4,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import game.collect.Sets; +import com.google.common.collect.Sets; + import game.color.TextColor; import game.entity.attributes.Attribute; import game.entity.attributes.AttributeModifier; diff --git a/java/src/game/item/ItemMetalBlock.java b/java/src/game/item/ItemMetalBlock.java index 68a09cb..d4939ca 100755 --- a/java/src/game/item/ItemMetalBlock.java +++ b/java/src/game/item/ItemMetalBlock.java @@ -4,8 +4,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.collect.Sets; + import game.block.Block; -import game.collect.Sets; import game.color.TextColor; import game.entity.attributes.Attribute; import game.entity.attributes.AttributeModifier; diff --git a/java/src/game/item/ItemPotion.java b/java/src/game/item/ItemPotion.java index d3cf2d1..7368b60 100755 --- a/java/src/game/item/ItemPotion.java +++ b/java/src/game/item/ItemPotion.java @@ -4,10 +4,12 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import java.util.Set; -import game.collect.Maps; -import game.collect.Sets; import game.color.TextColor; import game.entity.attributes.Attribute; import game.entity.attributes.AttributeModifier; diff --git a/java/src/game/item/ItemStack.java b/java/src/game/item/ItemStack.java index 11c034a..7d78a9a 100755 --- a/java/src/game/item/ItemStack.java +++ b/java/src/game/item/ItemStack.java @@ -4,11 +4,13 @@ import java.text.DecimalFormat; import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import java.util.Set; import game.block.Block; -import game.collect.Lists; -import game.collect.Maps; import game.color.TextColor; import game.enchantment.Enchantment; import game.enchantment.EnchantmentDurability; diff --git a/java/src/game/item/ItemSword.java b/java/src/game/item/ItemSword.java index bad7e9c..271c7c1 100755 --- a/java/src/game/item/ItemSword.java +++ b/java/src/game/item/ItemSword.java @@ -3,8 +3,9 @@ package game.item; import java.util.Map; import java.util.Set; +import com.google.common.collect.Sets; + import game.block.Block; -import game.collect.Sets; import game.entity.attributes.Attribute; import game.entity.attributes.AttributeModifier; import game.entity.attributes.Attributes; diff --git a/java/src/game/item/ItemTool.java b/java/src/game/item/ItemTool.java index c7d1427..eb3c1f4 100755 --- a/java/src/game/item/ItemTool.java +++ b/java/src/game/item/ItemTool.java @@ -3,8 +3,9 @@ package game.item; import java.util.Map; import java.util.Set; +import com.google.common.collect.Sets; + import game.block.Block; -import game.collect.Sets; import game.entity.attributes.Attribute; import game.entity.attributes.AttributeModifier; import game.entity.attributes.Attributes; diff --git a/java/src/game/log/Log.java b/java/src/game/log/Log.java index 216db62..fd88ca8 100644 --- a/java/src/game/log/Log.java +++ b/java/src/game/log/Log.java @@ -4,8 +4,9 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; +import com.google.common.collect.Lists; + import game.Game; -import game.collect.Lists; import game.color.TextColor; public enum Log { diff --git a/java/src/game/model/BakedModel.java b/java/src/game/model/BakedModel.java index 6c8c8ae..20a00f2 100755 --- a/java/src/game/model/BakedModel.java +++ b/java/src/game/model/BakedModel.java @@ -3,7 +3,8 @@ package game.model; import java.util.ArrayList; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.renderer.blockmodel.BakedQuad; import game.renderer.blockmodel.BreakingFour; import game.renderer.blockmodel.ModelBlock; diff --git a/java/src/game/model/ModelBakery.java b/java/src/game/model/ModelBakery.java index 4621e61..21e6343 100755 --- a/java/src/game/model/ModelBakery.java +++ b/java/src/game/model/ModelBakery.java @@ -5,11 +5,13 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import java.util.Set; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; import game.init.BlockRegistry; import game.init.FluidRegistry; import game.init.IRegistry; diff --git a/java/src/game/model/ModelManager.java b/java/src/game/model/ModelManager.java index 4577303..f774bcd 100755 --- a/java/src/game/model/ModelManager.java +++ b/java/src/game/model/ModelManager.java @@ -3,11 +3,13 @@ package game.model; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Maps; + import java.util.Set; import game.block.Block; import game.block.BlockLiquid; -import game.collect.Maps; import game.init.BlockRegistry; import game.init.Blocks; import game.init.FluidRegistry; diff --git a/java/src/game/model/ModelRotation.java b/java/src/game/model/ModelRotation.java index ca9d5d0..caa78b9 100755 --- a/java/src/game/model/ModelRotation.java +++ b/java/src/game/model/ModelRotation.java @@ -2,7 +2,8 @@ package game.model; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.renderer.Matrix4f; import game.renderer.Vector3f; import game.util.ExtMath; diff --git a/java/src/game/nbt/NBTParser.java b/java/src/game/nbt/NBTParser.java index e4a2e97..e367ae8 100755 --- a/java/src/game/nbt/NBTParser.java +++ b/java/src/game/nbt/NBTParser.java @@ -3,7 +3,7 @@ package game.nbt; import java.util.Stack; import java.util.regex.Pattern; -import game.collect.Lists; +import com.google.common.collect.Lists; public class NBTParser { diff --git a/java/src/game/nbt/NBTTagCompound.java b/java/src/game/nbt/NBTTagCompound.java index 4606414..3feb7dd 100755 --- a/java/src/game/nbt/NBTTagCompound.java +++ b/java/src/game/nbt/NBTTagCompound.java @@ -5,9 +5,10 @@ import java.io.DataOutput; import java.io.IOException; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; -import game.collect.Maps; +import com.google.common.collect.Maps; + +import java.util.Set; public class NBTTagCompound extends NBTBase { diff --git a/java/src/game/nbt/NBTTagList.java b/java/src/game/nbt/NBTTagList.java index 2ce7cfa..612dd56 100755 --- a/java/src/game/nbt/NBTTagList.java +++ b/java/src/game/nbt/NBTTagList.java @@ -6,7 +6,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.log.Log; public class NBTTagList extends NBTBase diff --git a/java/src/game/net/bootstrap/AbstractBootstrap.java b/java/src/game/net/bootstrap/AbstractBootstrap.java deleted file mode 100644 index 20ed671..0000000 --- a/java/src/game/net/bootstrap/AbstractBootstrap.java +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.bootstrap; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.LinkedHashMap; -import java.util.Map; - -import game.net.channel.Channel; -import game.net.channel.ChannelException; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelFutureListener; -import game.net.channel.ChannelHandler; -import game.net.channel.ChannelOption; -import game.net.channel.ChannelPromise; -import game.net.channel.DefaultChannelPromise; -import game.net.channel.EventLoopGroup; -import game.net.util.AttributeKey; -import game.net.util.concurrent.EventExecutor; -import game.net.util.concurrent.GlobalEventExecutor; -import game.net.util.internal.StringUtil; - -/** - * {@link AbstractBootstrap} is a helper class that makes it easy to bootstrap a {@link Channel}. It support - * method-chaining to provide an easy way to configure the {@link AbstractBootstrap}. - * - *

When not used in a {@link ServerBootstrap} context, the {@link #bind()} methods are useful for connectionless - * transports such as datagram (UDP).

- */ -public abstract class AbstractBootstrap, C extends Channel> implements Cloneable { - - private volatile EventLoopGroup group; - private volatile ChannelFactory channelFactory; - private volatile SocketAddress localAddress; - private final Map, Object> options = new LinkedHashMap, Object>(); - private final Map, Object> attrs = new LinkedHashMap, Object>(); - private volatile ChannelHandler handler; - - AbstractBootstrap() { - // Disallow extending from a different package. - } - - AbstractBootstrap(AbstractBootstrap bootstrap) { - group = bootstrap.group; - channelFactory = bootstrap.channelFactory; - handler = bootstrap.handler; - localAddress = bootstrap.localAddress; - synchronized (bootstrap.options) { - options.putAll(bootstrap.options); - } - synchronized (bootstrap.attrs) { - attrs.putAll(bootstrap.attrs); - } - } - - /** - * The {@link EventLoopGroup} which is used to handle all the events for the to-be-creates - * {@link Channel} - */ - - public B group(EventLoopGroup group) { - if (group == null) { - throw new NullPointerException("group"); - } - if (this.group != null) { - throw new IllegalStateException("group set already"); - } - this.group = group; - return (B) this; - } - - /** - * The {@link Class} which is used to create {@link Channel} instances from. - * You either use this or {@link #channelFactory(ChannelFactory)} if your - * {@link Channel} implementation has no no-args constructor. - */ - public B channel(Class channelClass) { - if (channelClass == null) { - throw new NullPointerException("channelClass"); - } - return channelFactory(new BootstrapChannelFactory(channelClass)); - } - - /** - * {@link ChannelFactory} which is used to create {@link Channel} instances from - * when calling {@link #bind()}. This method is usually only used if {@link #channel(Class)} - * is not working for you because of some more complex needs. If your {@link Channel} implementation - * has a no-args constructor, its highly recommend to just use {@link #channel(Class)} for - * simplify your code. - */ - - public B channelFactory(ChannelFactory channelFactory) { - if (channelFactory == null) { - throw new NullPointerException("channelFactory"); - } - if (this.channelFactory != null) { - throw new IllegalStateException("channelFactory set already"); - } - - this.channelFactory = channelFactory; - return (B) this; - } - - /** - * The {@link SocketAddress} which is used to bind the local "end" to. - * - */ - - public B localAddress(SocketAddress localAddress) { - this.localAddress = localAddress; - return (B) this; - } - - /** - * @see {@link #localAddress(SocketAddress)} - */ - public B localAddress(int inetPort) { - return localAddress(new InetSocketAddress(inetPort)); - } - - /** - * @see {@link #localAddress(SocketAddress)} - */ - public B localAddress(String inetHost, int inetPort) { - return localAddress(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * @see {@link #localAddress(SocketAddress)} - */ - public B localAddress(InetAddress inetHost, int inetPort) { - return localAddress(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Allow to specify a {@link ChannelOption} which is used for the {@link Channel} instances once they got - * created. Use a value of {@code null} to remove a previous set {@link ChannelOption}. - */ - - public B option(ChannelOption option, T value) { - if (option == null) { - throw new NullPointerException("option"); - } - if (value == null) { - synchronized (options) { - options.remove(option); - } - } else { - synchronized (options) { - options.put(option, value); - } - } - return (B) this; - } - - /** - * Allow to specify an initial attribute of the newly created {@link Channel}. If the {@code value} is - * {@code null}, the attribute of the specified {@code key} is removed. - */ - public B attr(AttributeKey key, T value) { - if (key == null) { - throw new NullPointerException("key"); - } - if (value == null) { - synchronized (attrs) { - attrs.remove(key); - } - } else { - synchronized (attrs) { - attrs.put(key, value); - } - } - - - B b = (B) this; - return b; - } - - /** - * Validate all the parameters. Sub-classes may override this, but should - * call the super method in that case. - */ - - public B validate() { - if (group == null) { - throw new IllegalStateException("group not set"); - } - if (channelFactory == null) { - throw new IllegalStateException("channel or channelFactory not set"); - } - return (B) this; - } - - /** - * Returns a deep clone of this bootstrap which has the identical configuration. This method is useful when making - * multiple {@link Channel}s with similar settings. Please note that this method does not clone the - * {@link EventLoopGroup} deeply but shallowly, making the group a shared resource. - */ - @Override - - public abstract B clone(); - - /** - * Create a new {@link Channel} and register it with an {@link EventLoop}. - */ - public ChannelFuture register() { - validate(); - return initAndRegister(); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind() { - validate(); - SocketAddress localAddress = this.localAddress; - if (localAddress == null) { - throw new IllegalStateException("localAddress not set"); - } - return doBind(localAddress); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(int inetPort) { - return bind(new InetSocketAddress(inetPort)); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(String inetHost, int inetPort) { - return bind(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(InetAddress inetHost, int inetPort) { - return bind(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(SocketAddress localAddress) { - validate(); - if (localAddress == null) { - throw new NullPointerException("localAddress"); - } - return doBind(localAddress); - } - - private ChannelFuture doBind(final SocketAddress localAddress) { - final ChannelFuture regFuture = initAndRegister(); - final Channel channel = regFuture.channel(); - if (regFuture.cause() != null) { - return regFuture; - } - - final ChannelPromise promise; - if (regFuture.isDone()) { - promise = channel.newPromise(); - doBind0(regFuture, channel, localAddress, promise); - } else { - // Registration future is almost always fulfilled already, but just in case it's not. - promise = new PendingRegistrationPromise(channel); - regFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - doBind0(regFuture, channel, localAddress, promise); - } - }); - } - - return promise; - } - - final ChannelFuture initAndRegister() { - final Channel channel = channelFactory().newChannel(); - try { - init(channel); - } catch (Throwable t) { - channel.unsafe().closeForcibly(); - // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor - return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t); - } - - ChannelFuture regFuture = group().register(channel); - if (regFuture.cause() != null) { - if (channel.isRegistered()) { - channel.close(); - } else { - channel.unsafe().closeForcibly(); - } - } - - // If we are here and the promise is not failed, it's one of the following cases: - // 1) If we attempted registration from the event loop, the registration has been completed at this point. - // i.e. It's safe to attempt bind() or connect() now because the channel has been registered. - // 2) If we attempted registration from the other thread, the registration request has been successfully - // added to the event loop's task queue for later execution. - // i.e. It's safe to attempt bind() or connect() now: - // because bind() or connect() will be executed *after* the scheduled registration task is executed - // because register(), bind(), and connect() are all bound to the same thread. - - return regFuture; - } - - abstract void init(Channel channel) throws Exception; - - private static void doBind0( - final ChannelFuture regFuture, final Channel channel, - final SocketAddress localAddress, final ChannelPromise promise) { - - // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up - // the pipeline in its channelRegistered() implementation. - channel.eventLoop().execute(new Runnable() { - @Override - public void run() { - if (regFuture.isSuccess()) { - channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); - } else { - promise.setFailure(regFuture.cause()); - } - } - }); - } - - /** - * the {@link ChannelHandler} to use for serving the requests. - */ - - public B handler(ChannelHandler handler) { - if (handler == null) { - throw new NullPointerException("handler"); - } - this.handler = handler; - return (B) this; - } - - final SocketAddress localAddress() { - return localAddress; - } - - final ChannelFactory channelFactory() { - return channelFactory; - } - - final ChannelHandler handler() { - return handler; - } - - /** - * Return the configured {@link EventLoopGroup} or {@code null} if non is configured yet. - */ - public final EventLoopGroup group() { - return group; - } - - final Map, Object> options() { - return options; - } - - final Map, Object> attrs() { - return attrs; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append(StringUtil.simpleClassName(this)); - buf.append('('); - if (group != null) { - buf.append("group: "); - buf.append(StringUtil.simpleClassName(group)); - buf.append(", "); - } - if (channelFactory != null) { - buf.append("channelFactory: "); - buf.append(channelFactory); - buf.append(", "); - } - if (localAddress != null) { - buf.append("localAddress: "); - buf.append(localAddress); - buf.append(", "); - } - synchronized (options) { - if (!options.isEmpty()) { - buf.append("options: "); - buf.append(options); - buf.append(", "); - } - } - synchronized (attrs) { - if (!attrs.isEmpty()) { - buf.append("attrs: "); - buf.append(attrs); - buf.append(", "); - } - } - if (handler != null) { - buf.append("handler: "); - buf.append(handler); - buf.append(", "); - } - if (buf.charAt(buf.length() - 1) == '(') { - buf.append(')'); - } else { - buf.setCharAt(buf.length() - 2, ')'); - buf.setLength(buf.length() - 1); - } - return buf.toString(); - } - - private static final class BootstrapChannelFactory implements ChannelFactory { - private final Class clazz; - - BootstrapChannelFactory(Class clazz) { - this.clazz = clazz; - } - - @Override - public T newChannel() { - try { - return clazz.newInstance(); - } catch (Throwable t) { - throw new ChannelException("Unable to create Channel from class " + clazz, t); - } - } - - @Override - public String toString() { - return StringUtil.simpleClassName(clazz) + ".class"; - } - } - - private static final class PendingRegistrationPromise extends DefaultChannelPromise { - private PendingRegistrationPromise(Channel channel) { - super(channel); - } - - @Override - protected EventExecutor executor() { - if (channel().isRegistered()) { - // If the registration was a success we can just call super.executor() which will return - // channel.eventLoop(). - // - // See https://github.com/netty/netty/issues/2586 - return super.executor(); - } - // The registration failed so we can only use the GlobalEventExecutor as last resort to notify. - return GlobalEventExecutor.INSTANCE; - } - } -} diff --git a/java/src/game/net/bootstrap/Bootstrap.java b/java/src/game/net/bootstrap/Bootstrap.java deleted file mode 100644 index 5f55a60..0000000 --- a/java/src/game/net/bootstrap/Bootstrap.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.bootstrap; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Map; -import java.util.Map.Entry; - -import game.net.channel.Channel; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelFutureListener; -import game.net.channel.ChannelOption; -import game.net.channel.ChannelPipeline; -import game.net.channel.ChannelPromise; -import game.net.util.AttributeKey; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A {@link Bootstrap} that makes it easy to bootstrap a {@link Channel} to use - * for clients. - * - *

The {@link #bind()} methods are useful in combination with connectionless transports such as datagram (UDP). - * For regular TCP connections, please use the provided {@link #connect()} methods.

- */ -public final class Bootstrap extends AbstractBootstrap { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class); - - private volatile SocketAddress remoteAddress; - - public Bootstrap() { } - - private Bootstrap(Bootstrap bootstrap) { - super(bootstrap); - remoteAddress = bootstrap.remoteAddress; - } - - /** - * The {@link SocketAddress} to connect to once the {@link #connect()} method - * is called. - */ - public Bootstrap remoteAddress(SocketAddress remoteAddress) { - this.remoteAddress = remoteAddress; - return this; - } - - /** - * @see {@link #remoteAddress(SocketAddress)} - */ - public Bootstrap remoteAddress(String inetHost, int inetPort) { - remoteAddress = new InetSocketAddress(inetHost, inetPort); - return this; - } - - /** - * @see {@link #remoteAddress(SocketAddress)} - */ - public Bootstrap remoteAddress(InetAddress inetHost, int inetPort) { - remoteAddress = new InetSocketAddress(inetHost, inetPort); - return this; - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect() { - validate(); - SocketAddress remoteAddress = this.remoteAddress; - if (remoteAddress == null) { - throw new IllegalStateException("remoteAddress not set"); - } - - return doConnect(remoteAddress, localAddress()); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(String inetHost, int inetPort) { - return connect(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(InetAddress inetHost, int inetPort) { - return connect(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(SocketAddress remoteAddress) { - if (remoteAddress == null) { - throw new NullPointerException("remoteAddress"); - } - - validate(); - return doConnect(remoteAddress, localAddress()); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - if (remoteAddress == null) { - throw new NullPointerException("remoteAddress"); - } - validate(); - return doConnect(remoteAddress, localAddress); - } - - /** - * @see {@link #connect()} - */ - private ChannelFuture doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) { - final ChannelFuture regFuture = initAndRegister(); - final Channel channel = regFuture.channel(); - if (regFuture.cause() != null) { - return regFuture; - } - - final ChannelPromise promise = channel.newPromise(); - if (regFuture.isDone()) { - doConnect0(regFuture, channel, remoteAddress, localAddress, promise); - } else { - regFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - doConnect0(regFuture, channel, remoteAddress, localAddress, promise); - } - }); - } - - return promise; - } - - private static void doConnect0( - final ChannelFuture regFuture, final Channel channel, - final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { - - // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up - // the pipeline in its channelRegistered() implementation. - channel.eventLoop().execute(new Runnable() { - @Override - public void run() { - if (regFuture.isSuccess()) { - if (localAddress == null) { - channel.connect(remoteAddress, promise); - } else { - channel.connect(remoteAddress, localAddress, promise); - } - promise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); - } else { - promise.setFailure(regFuture.cause()); - } - } - }); - } - - @Override - - void init(Channel channel) throws Exception { - ChannelPipeline p = channel.pipeline(); - p.addLast(handler()); - - final Map, Object> options = options(); - synchronized (options) { - for (Entry, Object> e: options.entrySet()) { - try { - if (!channel.config().setOption((ChannelOption) e.getKey(), e.getValue())) { - logger.warn("Unknown channel option: " + e); - } - } catch (Throwable t) { - logger.warn("Failed to set a channel option: " + channel, t); - } - } - } - - final Map, Object> attrs = attrs(); - synchronized (attrs) { - for (Entry, Object> e: attrs.entrySet()) { - channel.attr((AttributeKey) e.getKey()).set(e.getValue()); - } - } - } - - @Override - public Bootstrap validate() { - super.validate(); - if (handler() == null) { - throw new IllegalStateException("handler not set"); - } - return this; - } - - @Override - - public Bootstrap clone() { - return new Bootstrap(this); - } - - @Override - public String toString() { - if (remoteAddress == null) { - return super.toString(); - } - - StringBuilder buf = new StringBuilder(super.toString()); - buf.setLength(buf.length() - 1); - buf.append(", remoteAddress: "); - buf.append(remoteAddress); - buf.append(')'); - - return buf.toString(); - } -} diff --git a/java/src/game/net/bootstrap/ChannelFactory.java b/java/src/game/net/bootstrap/ChannelFactory.java deleted file mode 100644 index f2c2977..0000000 --- a/java/src/game/net/bootstrap/ChannelFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.bootstrap; - -import game.net.channel.Channel; - -/** - * Factory that creates a new {@link Channel} on {@link Bootstrap#bind()}, {@link Bootstrap#connect()}, and - * {@link ServerBootstrap#bind()}. - */ -public interface ChannelFactory { - /** - * Creates a new channel. - */ - T newChannel(); -} diff --git a/java/src/game/net/bootstrap/ServerBootstrap.java b/java/src/game/net/bootstrap/ServerBootstrap.java deleted file mode 100644 index 889610a..0000000 --- a/java/src/game/net/bootstrap/ServerBootstrap.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.bootstrap; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.TimeUnit; - -import game.net.channel.Channel; -import game.net.channel.ChannelConfig; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelFutureListener; -import game.net.channel.ChannelHandler; -import game.net.channel.ChannelHandlerContext; -import game.net.channel.ChannelInboundHandlerAdapter; -import game.net.channel.ChannelInitializer; -import game.net.channel.ChannelOption; -import game.net.channel.ChannelPipeline; -import game.net.channel.EventLoopGroup; -import game.net.channel.ServerChannel; -import game.net.util.AttributeKey; -import game.net.util.internal.StringUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * {@link Bootstrap} sub-class which allows easy bootstrap of {@link ServerChannel} - * - */ -public final class ServerBootstrap extends AbstractBootstrap { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class); - - private final Map, Object> childOptions = new LinkedHashMap, Object>(); - private final Map, Object> childAttrs = new LinkedHashMap, Object>(); - private volatile EventLoopGroup childGroup; - private volatile ChannelHandler childHandler; - - public ServerBootstrap() { } - - private ServerBootstrap(ServerBootstrap bootstrap) { - super(bootstrap); - childGroup = bootstrap.childGroup; - childHandler = bootstrap.childHandler; - synchronized (bootstrap.childOptions) { - childOptions.putAll(bootstrap.childOptions); - } - synchronized (bootstrap.childAttrs) { - childAttrs.putAll(bootstrap.childAttrs); - } - } - - /** - * Specify the {@link EventLoopGroup} which is used for the parent (acceptor) and the child (client). - */ - @Override - public ServerBootstrap group(EventLoopGroup group) { - return group(group, group); - } - - /** - * Set the {@link EventLoopGroup} for the parent (acceptor) and the child (client). These - * {@link EventLoopGroup}'s are used to handle all the events and IO for {@link SocketChannel} and - * {@link Channel}'s. - */ - public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { - super.group(parentGroup); - if (childGroup == null) { - throw new NullPointerException("childGroup"); - } - if (this.childGroup != null) { - throw new IllegalStateException("childGroup set already"); - } - this.childGroup = childGroup; - return this; - } - - /** - * Allow to specify a {@link ChannelOption} which is used for the {@link Channel} instances once they get created - * (after the acceptor accepted the {@link Channel}). Use a value of {@code null} to remove a previous set - * {@link ChannelOption}. - */ - public ServerBootstrap childOption(ChannelOption childOption, T value) { - if (childOption == null) { - throw new NullPointerException("childOption"); - } - if (value == null) { - synchronized (childOptions) { - childOptions.remove(childOption); - } - } else { - synchronized (childOptions) { - childOptions.put(childOption, value); - } - } - return this; - } - - /** - * Set the specific {@link AttributeKey} with the given value on every child {@link Channel}. If the value is - * {@code null} the {@link AttributeKey} is removed - */ - public ServerBootstrap childAttr(AttributeKey childKey, T value) { - if (childKey == null) { - throw new NullPointerException("childKey"); - } - if (value == null) { - childAttrs.remove(childKey); - } else { - childAttrs.put(childKey, value); - } - return this; - } - - /** - * Set the {@link ChannelHandler} which is used to serve the request for the {@link Channel}'s. - */ - public ServerBootstrap childHandler(ChannelHandler childHandler) { - if (childHandler == null) { - throw new NullPointerException("childHandler"); - } - this.childHandler = childHandler; - return this; - } - - /** - * Return the configured {@link EventLoopGroup} which will be used for the child channels or {@code null} - * if non is configured yet. - */ - public EventLoopGroup childGroup() { - return childGroup; - } - - @Override - void init(Channel channel) throws Exception { - final Map, Object> options = options(); - synchronized (options) { - channel.config().setOptions(options); - } - - final Map, Object> attrs = attrs(); - synchronized (attrs) { - for (Entry, Object> e: attrs.entrySet()) { - - AttributeKey key = (AttributeKey) e.getKey(); - channel.attr(key).set(e.getValue()); - } - } - - ChannelPipeline p = channel.pipeline(); - if (handler() != null) { - p.addLast(handler()); - } - - final EventLoopGroup currentChildGroup = childGroup; - final ChannelHandler currentChildHandler = childHandler; - final Entry, Object>[] currentChildOptions; - final Entry, Object>[] currentChildAttrs; - synchronized (childOptions) { - currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size())); - } - synchronized (childAttrs) { - currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size())); - } - - p.addLast(new ChannelInitializer() { - @Override - public void initChannel(Channel ch) throws Exception { - ch.pipeline().addLast(new ServerBootstrapAcceptor( - currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); - } - }); - } - - @Override - public ServerBootstrap validate() { - super.validate(); - if (childHandler == null) { - throw new IllegalStateException("childHandler not set"); - } - if (childGroup == null) { - logger.warn("childGroup is not set. Using parentGroup instead."); - childGroup = group(); - } - return this; - } - - - private static Entry, Object>[] newOptionArray(int size) { - return new Entry[size]; - } - - - private static Entry, Object>[] newAttrArray(int size) { - return new Entry[size]; - } - - private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter { - - private final EventLoopGroup childGroup; - private final ChannelHandler childHandler; - private final Entry, Object>[] childOptions; - private final Entry, Object>[] childAttrs; - - ServerBootstrapAcceptor( - EventLoopGroup childGroup, ChannelHandler childHandler, - Entry, Object>[] childOptions, Entry, Object>[] childAttrs) { - this.childGroup = childGroup; - this.childHandler = childHandler; - this.childOptions = childOptions; - this.childAttrs = childAttrs; - } - - @Override - - public void channelRead(ChannelHandlerContext ctx, Object msg) { - final Channel child = (Channel) msg; - - child.pipeline().addLast(childHandler); - - for (Entry, Object> e: childOptions) { - try { - if (!child.config().setOption((ChannelOption) e.getKey(), e.getValue())) { - logger.warn("Unknown channel option: " + e); - } - } catch (Throwable t) { - logger.warn("Failed to set a channel option: " + child, t); - } - } - - for (Entry, Object> e: childAttrs) { - child.attr((AttributeKey) e.getKey()).set(e.getValue()); - } - - try { - childGroup.register(child).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - forceClose(child, future.cause()); - } - } - }); - } catch (Throwable t) { - forceClose(child, t); - } - } - - private static void forceClose(Channel child, Throwable t) { - child.unsafe().closeForcibly(); - logger.warn("Failed to register an accepted channel: " + child, t); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - final ChannelConfig config = ctx.channel().config(); - if (config.isAutoRead()) { - // stop accept new connections for 1 second to allow the channel to recover - // See https://github.com/netty/netty/issues/1328 - config.setAutoRead(false); - ctx.channel().eventLoop().schedule(new Runnable() { - @Override - public void run() { - config.setAutoRead(true); - } - }, 1, TimeUnit.SECONDS); - } - // still let the exceptionCaught event flow through the pipeline to give the user - // a chance to do something with it - ctx.fireExceptionCaught(cause); - } - } - - @Override - - public ServerBootstrap clone() { - return new ServerBootstrap(this); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(super.toString()); - buf.setLength(buf.length() - 1); - buf.append(", "); - if (childGroup != null) { - buf.append("childGroup: "); - buf.append(StringUtil.simpleClassName(childGroup)); - buf.append(", "); - } - synchronized (childOptions) { - if (!childOptions.isEmpty()) { - buf.append("childOptions: "); - buf.append(childOptions); - buf.append(", "); - } - } - synchronized (childAttrs) { - if (!childAttrs.isEmpty()) { - buf.append("childAttrs: "); - buf.append(childAttrs); - buf.append(", "); - } - } - if (childHandler != null) { - buf.append("childHandler: "); - buf.append(childHandler); - buf.append(", "); - } - if (buf.charAt(buf.length() - 1) == '(') { - buf.append(')'); - } else { - buf.setCharAt(buf.length() - 2, ')'); - buf.setLength(buf.length() - 1); - } - - return buf.toString(); - } -} diff --git a/java/src/game/net/buffer/AbstractByteBuf.java b/java/src/game/net/buffer/AbstractByteBuf.java deleted file mode 100644 index a5e40be..0000000 --- a/java/src/game/net/buffer/AbstractByteBuf.java +++ /dev/null @@ -1,1190 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import game.net.util.IllegalReferenceCountException; -import game.net.util.ResourceLeakDetector; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.StringUtil; - - -/** - * A skeletal implementation of a buffer. - */ -public abstract class AbstractByteBuf extends ByteBuf { - - static final ResourceLeakDetector leakDetector = new ResourceLeakDetector(ByteBuf.class); - - int readerIndex; - int writerIndex; - private int markedReaderIndex; - private int markedWriterIndex; - - private int maxCapacity; - - private SwappedByteBuf swappedBuf; - - protected AbstractByteBuf(int maxCapacity) { - if (maxCapacity < 0) { - throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)"); - } - this.maxCapacity = maxCapacity; - } - - @Override - public int maxCapacity() { - return maxCapacity; - } - - protected final void maxCapacity(int maxCapacity) { - this.maxCapacity = maxCapacity; - } - - @Override - public int readerIndex() { - return readerIndex; - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - if (readerIndex < 0 || readerIndex > writerIndex) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex: %d (expected: 0 <= readerIndex <= writerIndex(%d))", readerIndex, writerIndex)); - } - this.readerIndex = readerIndex; - return this; - } - - @Override - public int writerIndex() { - return writerIndex; - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - if (writerIndex < readerIndex || writerIndex > capacity()) { - throw new IndexOutOfBoundsException(String.format( - "writerIndex: %d (expected: readerIndex(%d) <= writerIndex <= capacity(%d))", - writerIndex, readerIndex, capacity())); - } - this.writerIndex = writerIndex; - return this; - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex: %d, writerIndex: %d (expected: 0 <= readerIndex <= writerIndex <= capacity(%d))", - readerIndex, writerIndex, capacity())); - } - this.readerIndex = readerIndex; - this.writerIndex = writerIndex; - return this; - } - - @Override - public ByteBuf clear() { - readerIndex = writerIndex = 0; - return this; - } - - @Override - public boolean isReadable() { - return writerIndex > readerIndex; - } - - @Override - public boolean isReadable(int numBytes) { - return writerIndex - readerIndex >= numBytes; - } - - @Override - public boolean isWritable() { - return capacity() > writerIndex; - } - - @Override - public boolean isWritable(int numBytes) { - return capacity() - writerIndex >= numBytes; - } - - @Override - public int readableBytes() { - return writerIndex - readerIndex; - } - - @Override - public int writableBytes() { - return capacity() - writerIndex; - } - - @Override - public int maxWritableBytes() { - return maxCapacity() - writerIndex; - } - - @Override - public ByteBuf markReaderIndex() { - markedReaderIndex = readerIndex; - return this; - } - - @Override - public ByteBuf resetReaderIndex() { - readerIndex(markedReaderIndex); - return this; - } - - @Override - public ByteBuf markWriterIndex() { - markedWriterIndex = writerIndex; - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - writerIndex = markedWriterIndex; - return this; - } - - @Override - public ByteBuf discardReadBytes() { - ensureAccessible(); - if (readerIndex == 0) { - return this; - } - - if (readerIndex != writerIndex) { - setBytes(0, this, readerIndex, writerIndex - readerIndex); - writerIndex -= readerIndex; - adjustMarkers(readerIndex); - readerIndex = 0; - } else { - adjustMarkers(readerIndex); - writerIndex = readerIndex = 0; - } - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - ensureAccessible(); - if (readerIndex == 0) { - return this; - } - - if (readerIndex == writerIndex) { - adjustMarkers(readerIndex); - writerIndex = readerIndex = 0; - return this; - } - - if (readerIndex >= capacity() >>> 1) { - setBytes(0, this, readerIndex, writerIndex - readerIndex); - writerIndex -= readerIndex; - adjustMarkers(readerIndex); - readerIndex = 0; - } - return this; - } - - protected final void adjustMarkers(int decrement) { - int markedReaderIndex = this.markedReaderIndex; - if (markedReaderIndex <= decrement) { - this.markedReaderIndex = 0; - int markedWriterIndex = this.markedWriterIndex; - if (markedWriterIndex <= decrement) { - this.markedWriterIndex = 0; - } else { - this.markedWriterIndex = markedWriterIndex - decrement; - } - } else { - this.markedReaderIndex = markedReaderIndex - decrement; - markedWriterIndex -= decrement; - } - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException(String.format( - "minWritableBytes: %d (expected: >= 0)", minWritableBytes)); - } - - if (minWritableBytes <= writableBytes()) { - return this; - } - - if (minWritableBytes > maxCapacity - writerIndex) { - throw new IndexOutOfBoundsException(String.format( - "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s", - writerIndex, minWritableBytes, maxCapacity, this)); - } - - // Normalize the current capacity to the power of 2. - int newCapacity = calculateNewCapacity(writerIndex + minWritableBytes); - - // Adjust to the new capacity. - capacity(newCapacity); - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException(String.format( - "minWritableBytes: %d (expected: >= 0)", minWritableBytes)); - } - - if (minWritableBytes <= writableBytes()) { - return 0; - } - - if (minWritableBytes > maxCapacity - writerIndex) { - if (force) { - if (capacity() == maxCapacity()) { - return 1; - } - - capacity(maxCapacity()); - return 3; - } - } - - // Normalize the current capacity to the power of 2. - int newCapacity = calculateNewCapacity(writerIndex + minWritableBytes); - - // Adjust to the new capacity. - capacity(newCapacity); - return 2; - } - - private int calculateNewCapacity(int minNewCapacity) { - final int maxCapacity = this.maxCapacity; - final int threshold = 1048576 * 4; // 4 MiB page - - if (minNewCapacity == threshold) { - return threshold; - } - - // If over threshold, do not double but just increase by threshold. - if (minNewCapacity > threshold) { - int newCapacity = minNewCapacity / threshold * threshold; - if (newCapacity > maxCapacity - threshold) { - newCapacity = maxCapacity; - } else { - newCapacity += threshold; - } - return newCapacity; - } - - // Not over threshold. Double up to 4 MiB, starting from 64. - int newCapacity = 64; - while (newCapacity < minNewCapacity) { - newCapacity <<= 1; - } - - return Math.min(newCapacity, maxCapacity); - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order()) { - return this; - } - - SwappedByteBuf swappedBuf = this.swappedBuf; - if (swappedBuf == null) { - this.swappedBuf = swappedBuf = newSwappedByteBuf(); - } - return swappedBuf; - } - - /** - * Creates a new {@link SwappedByteBuf} for this {@link ByteBuf} instance. - */ - protected SwappedByteBuf newSwappedByteBuf() { - return new SwappedByteBuf(this); - } - - @Override - public byte getByte(int index) { - checkIndex(index); - return _getByte(index); - } - - protected abstract byte _getByte(int index); - - @Override - public boolean getBoolean(int index) { - return getByte(index) != 0; - } - - @Override - public short getUnsignedByte(int index) { - return (short) (getByte(index) & 0xFF); - } - - @Override - public short getShort(int index) { - checkIndex(index, 2); - return _getShort(index); - } - - protected abstract short _getShort(int index); - - @Override - public int getUnsignedShort(int index) { - return getShort(index) & 0xFFFF; - } - - @Override - public int getUnsignedMedium(int index) { - checkIndex(index, 3); - return _getUnsignedMedium(index); - } - - protected abstract int _getUnsignedMedium(int index); - - @Override - public int getMedium(int index) { - int value = getUnsignedMedium(index); - if ((value & 0x800000) != 0) { - value |= 0xff000000; - } - return value; - } - - @Override - public int getInt(int index) { - checkIndex(index, 4); - return _getInt(index); - } - - protected abstract int _getInt(int index); - - @Override - public long getUnsignedInt(int index) { - return getInt(index) & 0xFFFFFFFFL; - } - - @Override - public long getLong(int index) { - checkIndex(index, 8); - return _getLong(index); - } - - protected abstract long _getLong(int index); - - @Override - public char getChar(int index) { - return (char) getShort(index); - } - - @Override - public float getFloat(int index) { - return Float.intBitsToFloat(getInt(index)); - } - - @Override - public double getDouble(int index) { - return Double.longBitsToDouble(getLong(index)); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - getBytes(index, dst, 0, dst.length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - getBytes(index, dst, dst.writableBytes()); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - getBytes(index, dst, dst.writerIndex(), length); - dst.writerIndex(dst.writerIndex() + length); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - checkIndex(index); - _setByte(index, value); - return this; - } - - protected abstract void _setByte(int index, int value); - - @Override - public ByteBuf setBoolean(int index, boolean value) { - setByte(index, value ? 1 : 0); - return this; - } - - @Override - public ByteBuf setShort(int index, int value) { - checkIndex(index, 2); - _setShort(index, value); - return this; - } - - protected abstract void _setShort(int index, int value); - - @Override - public ByteBuf setChar(int index, int value) { - setShort(index, value); - return this; - } - - @Override - public ByteBuf setMedium(int index, int value) { - checkIndex(index, 3); - _setMedium(index, value); - return this; - } - - protected abstract void _setMedium(int index, int value); - - @Override - public ByteBuf setInt(int index, int value) { - checkIndex(index, 4); - _setInt(index, value); - return this; - } - - protected abstract void _setInt(int index, int value); - - @Override - public ByteBuf setFloat(int index, float value) { - setInt(index, Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - checkIndex(index, 8); - _setLong(index, value); - return this; - } - - protected abstract void _setLong(int index, long value); - - @Override - public ByteBuf setDouble(int index, double value) { - setLong(index, Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - setBytes(index, src, 0, src.length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - setBytes(index, src, src.readableBytes()); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - checkIndex(index, length); - if (src == null) { - throw new NullPointerException("src"); - } - if (length > src.readableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src)); - } - - setBytes(index, src, src.readerIndex(), length); - src.readerIndex(src.readerIndex() + length); - return this; - } - - @Override - public ByteBuf setZero(int index, int length) { - if (length == 0) { - return this; - } - - checkIndex(index, length); - - int nLong = length >>> 3; - int nBytes = length & 7; - for (int i = nLong; i > 0; i --) { - setLong(index, 0); - index += 8; - } - if (nBytes == 4) { - setInt(index, 0); - } else if (nBytes < 4) { - for (int i = nBytes; i > 0; i --) { - setByte(index, (byte) 0); - index ++; - } - } else { - setInt(index, 0); - index += 4; - for (int i = nBytes - 4; i > 0; i --) { - setByte(index, (byte) 0); - index ++; - } - } - return this; - } - - @Override - public byte readByte() { - checkReadableBytes(1); - int i = readerIndex; - byte b = getByte(i); - readerIndex = i + 1; - return b; - } - - @Override - public boolean readBoolean() { - return readByte() != 0; - } - - @Override - public short readUnsignedByte() { - return (short) (readByte() & 0xFF); - } - - @Override - public short readShort() { - checkReadableBytes(2); - short v = _getShort(readerIndex); - readerIndex += 2; - return v; - } - - @Override - public int readUnsignedShort() { - return readShort() & 0xFFFF; - } - - @Override - public int readMedium() { - int value = readUnsignedMedium(); - if ((value & 0x800000) != 0) { - value |= 0xff000000; - } - return value; - } - - @Override - public int readUnsignedMedium() { - checkReadableBytes(3); - int v = _getUnsignedMedium(readerIndex); - readerIndex += 3; - return v; - } - - @Override - public int readInt() { - checkReadableBytes(4); - int v = _getInt(readerIndex); - readerIndex += 4; - return v; - } - - @Override - public long readUnsignedInt() { - return readInt() & 0xFFFFFFFFL; - } - - @Override - public long readLong() { - checkReadableBytes(8); - long v = _getLong(readerIndex); - readerIndex += 8; - return v; - } - - @Override - public char readChar() { - return (char) readShort(); - } - - @Override - public float readFloat() { - return Float.intBitsToFloat(readInt()); - } - - @Override - public double readDouble() { - return Double.longBitsToDouble(readLong()); - } - - @Override - public ByteBuf readBytes(int length) { - checkReadableBytes(length); - if (length == 0) { - return Unpooled.EMPTY_BUFFER; - } - - // Use an unpooled heap buffer because there's no way to mandate a user to free the returned buffer. - ByteBuf buf = Unpooled.buffer(length, maxCapacity); - buf.writeBytes(this, readerIndex, length); - readerIndex += length; - return buf; - } - - @Override - public ByteBuf readSlice(int length) { - ByteBuf slice = slice(readerIndex, length); - readerIndex += length; - return slice; - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst) { - readBytes(dst, 0, dst.length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - readBytes(dst, dst.writableBytes()); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - if (length > dst.writableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds dst.writableBytes(%d) where dst is: %s", length, dst.writableBytes(), dst)); - } - readBytes(dst, dst.writerIndex(), length); - dst.writerIndex(dst.writerIndex() + length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst); - readerIndex += length; - return this; - } - - @Override - public int readBytes(GatheringByteChannel out, int length) - throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length); - readerIndex += readBytes; - return readBytes; - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - checkReadableBytes(length); - getBytes(readerIndex, out, length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf skipBytes(int length) { - checkReadableBytes(length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf writeBoolean(boolean value) { - writeByte(value ? 1 : 0); - return this; - } - - @Override - public ByteBuf writeByte(int value) { - ensureAccessible(); - ensureWritable(1); - _setByte(writerIndex++, value); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - ensureAccessible(); - ensureWritable(2); - _setShort(writerIndex, value); - writerIndex += 2; - return this; - } - - @Override - public ByteBuf writeMedium(int value) { - ensureAccessible(); - ensureWritable(3); - _setMedium(writerIndex, value); - writerIndex += 3; - return this; - } - - @Override - public ByteBuf writeInt(int value) { - ensureAccessible(); - ensureWritable(4); - _setInt(writerIndex, value); - writerIndex += 4; - return this; - } - - @Override - public ByteBuf writeLong(long value) { - ensureAccessible(); - ensureWritable(8); - _setLong(writerIndex, value); - writerIndex += 8; - return this; - } - - @Override - public ByteBuf writeChar(int value) { - writeShort(value); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - writeInt(Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - writeLong(Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - ensureAccessible(); - ensureWritable(length); - setBytes(writerIndex, src, srcIndex, length); - writerIndex += length; - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src) { - writeBytes(src, 0, src.length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - writeBytes(src, src.readableBytes()); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - if (length > src.readableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src)); - } - writeBytes(src, src.readerIndex(), length); - src.readerIndex(src.readerIndex() + length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - ensureAccessible(); - ensureWritable(length); - setBytes(writerIndex, src, srcIndex, length); - writerIndex += length; - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - ensureAccessible(); - int length = src.remaining(); - ensureWritable(length); - setBytes(writerIndex, src); - writerIndex += length; - return this; - } - - @Override - public int writeBytes(InputStream in, int length) - throws IOException { - ensureAccessible(); - ensureWritable(length); - int writtenBytes = setBytes(writerIndex, in, length); - if (writtenBytes > 0) { - writerIndex += writtenBytes; - } - return writtenBytes; - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - ensureWritable(length); - int writtenBytes = setBytes(writerIndex, in, length); - if (writtenBytes > 0) { - writerIndex += writtenBytes; - } - return writtenBytes; - } - - @Override - public ByteBuf writeZero(int length) { - if (length == 0) { - return this; - } - - ensureWritable(length); - checkIndex(writerIndex, length); - - int nLong = length >>> 3; - int nBytes = length & 7; - for (int i = nLong; i > 0; i --) { - writeLong(0); - } - if (nBytes == 4) { - writeInt(0); - } else if (nBytes < 4) { - for (int i = nBytes; i > 0; i --) { - writeByte((byte) 0); - } - } else { - writeInt(0); - for (int i = nBytes - 4; i > 0; i --) { - writeByte((byte) 0); - } - } - return this; - } - - @Override - public ByteBuf copy() { - return copy(readerIndex, readableBytes()); - } - - @Override - public ByteBuf duplicate() { - return new DuplicatedByteBuf(this); - } - - @Override - public ByteBuf slice() { - return slice(readerIndex, readableBytes()); - } - - @Override - public ByteBuf slice(int index, int length) { - if (length == 0) { - return Unpooled.EMPTY_BUFFER; - } - - return new SlicedByteBuf(this, index, length); - } - - @Override - public ByteBuffer nioBuffer() { - return nioBuffer(readerIndex, readableBytes()); - } - - @Override - public ByteBuffer[] nioBuffers() { - return nioBuffers(readerIndex, readableBytes()); - } - - @Override - public String toString(Charset charset) { - return toString(readerIndex, readableBytes(), charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - if (length == 0) { - return ""; - } - - ByteBuffer nioBuffer; - if (nioBufferCount() == 1) { - nioBuffer = nioBuffer(index, length); - } else { - nioBuffer = ByteBuffer.allocate(length); - getBytes(index, nioBuffer); - nioBuffer.flip(); - } - - return ByteBufUtil.decodeString(nioBuffer, charset); - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - return ByteBufUtil.indexOf(this, fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - return bytesBefore(readerIndex(), readableBytes(), value); - } - - @Override - public int bytesBefore(int length, byte value) { - checkReadableBytes(length); - return bytesBefore(readerIndex(), length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - int endIndex = indexOf(index, index + length, value); - if (endIndex < 0) { - return -1; - } - return endIndex - index; - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - int index = readerIndex; - int length = writerIndex - index; - ensureAccessible(); - return forEachByteAsc0(index, length, processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - return forEachByteAsc0(index, length, processor); - } - - private int forEachByteAsc0(int index, int length, ByteBufProcessor processor) { - if (processor == null) { - throw new NullPointerException("processor"); - } - - if (length == 0) { - return -1; - } - - final int endIndex = index + length; - int i = index; - try { - do { - if (processor.process(_getByte(i))) { - i ++; - } else { - return i; - } - } while (i < endIndex); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - - return -1; - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - int index = readerIndex; - int length = writerIndex - index; - ensureAccessible(); - return forEachByteDesc0(index, length, processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - - return forEachByteDesc0(index, length, processor); - } - - private int forEachByteDesc0(int index, int length, ByteBufProcessor processor) { - - if (processor == null) { - throw new NullPointerException("processor"); - } - - if (length == 0) { - return -1; - } - - int i = index + length - 1; - try { - do { - if (processor.process(_getByte(i))) { - i --; - } else { - return i; - } - } while (i >= index); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - - return -1; - } - - @Override - public int hashCode() { - return ByteBufUtil.hashCode(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o instanceof ByteBuf) { - return ByteBufUtil.equals(this, (ByteBuf) o); - } - return false; - } - - @Override - public int compareTo(ByteBuf that) { - return ByteBufUtil.compare(this, that); - } - - @Override - public String toString() { - if (refCnt() == 0) { - return StringUtil.simpleClassName(this) + "(freed)"; - } - - StringBuilder buf = new StringBuilder(); - buf.append(StringUtil.simpleClassName(this)); - buf.append("(ridx: "); - buf.append(readerIndex); - buf.append(", widx: "); - buf.append(writerIndex); - buf.append(", cap: "); - buf.append(capacity()); - if (maxCapacity != Integer.MAX_VALUE) { - buf.append('/'); - buf.append(maxCapacity); - } - - ByteBuf unwrapped = unwrap(); - if (unwrapped != null) { - buf.append(", unwrapped: "); - buf.append(unwrapped); - } - buf.append(')'); - return buf.toString(); - } - - protected final void checkIndex(int index) { - ensureAccessible(); - if (index < 0 || index >= capacity()) { - throw new IndexOutOfBoundsException(String.format( - "index: %d (expected: range(0, %d))", index, capacity())); - } - } - - protected final void checkIndex(int index, int fieldLength) { - ensureAccessible(); - if (fieldLength < 0) { - throw new IllegalArgumentException("length: " + fieldLength + " (expected: >= 0)"); - } - if (index < 0 || index > capacity() - fieldLength) { - throw new IndexOutOfBoundsException(String.format( - "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity())); - } - } - - protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) { - checkIndex(index, length); - if (srcIndex < 0 || srcIndex > srcCapacity - length) { - throw new IndexOutOfBoundsException(String.format( - "srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity)); - } - } - - protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) { - checkIndex(index, length); - if (dstIndex < 0 || dstIndex > dstCapacity - length) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity)); - } - } - - /** - * Throws an {@link IndexOutOfBoundsException} if the current - * {@linkplain #readableBytes() readable bytes} of this buffer is less - * than the specified value. - */ - protected final void checkReadableBytes(int minimumReadableBytes) { - ensureAccessible(); - if (minimumReadableBytes < 0) { - throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)"); - } - if (readerIndex > writerIndex - minimumReadableBytes) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s", - readerIndex, minimumReadableBytes, writerIndex, this)); - } - } - - /** - * Should be called by every method that tries to access the buffers content to check - * if the buffer was released before. - */ - protected final void ensureAccessible() { - if (refCnt() == 0) { - throw new IllegalReferenceCountException(0); - } - } -} diff --git a/java/src/game/net/buffer/AbstractByteBufAllocator.java b/java/src/game/net/buffer/AbstractByteBufAllocator.java deleted file mode 100644 index 40aaa93..0000000 --- a/java/src/game/net/buffer/AbstractByteBufAllocator.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import game.net.util.ResourceLeak; -import game.net.util.ResourceLeakDetector; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.StringUtil; - -/** - * Skeletal {@link ByteBufAllocator} implementation to extend. - */ -public abstract class AbstractByteBufAllocator implements ByteBufAllocator { - private static final int DEFAULT_INITIAL_CAPACITY = 256; - private static final int DEFAULT_MAX_COMPONENTS = 16; - - protected static ByteBuf toLeakAwareBuffer(ByteBuf buf) { - ResourceLeak leak; - switch (ResourceLeakDetector.getLevel()) { - case SIMPLE: - leak = AbstractByteBuf.leakDetector.open(buf); - if (leak != null) { - buf = new SimpleLeakAwareByteBuf(buf, leak); - } - break; - case ADVANCED: - case PARANOID: - leak = AbstractByteBuf.leakDetector.open(buf); - if (leak != null) { - buf = new AdvancedLeakAwareByteBuf(buf, leak); - } - break; - } - return buf; - } - - private final boolean directByDefault; - private final ByteBuf emptyBuf; - - /** - * Instance use heap buffers by default - */ - protected AbstractByteBufAllocator() { - this(false); - } - - /** - * Create new instance - * - * @param preferDirect {@code true} if {@link #buffer(int)} should try to allocate a direct buffer rather than - * a heap buffer - */ - protected AbstractByteBufAllocator(boolean preferDirect) { - directByDefault = preferDirect && PlatformDependent.hasUnsafe(); - emptyBuf = new EmptyByteBuf(this); - } - - @Override - public ByteBuf buffer() { - if (directByDefault) { - return directBuffer(); - } - return heapBuffer(); - } - - @Override - public ByteBuf buffer(int initialCapacity) { - if (directByDefault) { - return directBuffer(initialCapacity); - } - return heapBuffer(initialCapacity); - } - - @Override - public ByteBuf buffer(int initialCapacity, int maxCapacity) { - if (directByDefault) { - return directBuffer(initialCapacity, maxCapacity); - } - return heapBuffer(initialCapacity, maxCapacity); - } - - @Override - public ByteBuf ioBuffer() { - if (PlatformDependent.hasUnsafe()) { - return directBuffer(DEFAULT_INITIAL_CAPACITY); - } - return heapBuffer(DEFAULT_INITIAL_CAPACITY); - } - - @Override - public ByteBuf ioBuffer(int initialCapacity) { - if (PlatformDependent.hasUnsafe()) { - return directBuffer(initialCapacity); - } - return heapBuffer(initialCapacity); - } - - @Override - public ByteBuf ioBuffer(int initialCapacity, int maxCapacity) { - if (PlatformDependent.hasUnsafe()) { - return directBuffer(initialCapacity, maxCapacity); - } - return heapBuffer(initialCapacity, maxCapacity); - } - - @Override - public ByteBuf heapBuffer() { - return heapBuffer(DEFAULT_INITIAL_CAPACITY, Integer.MAX_VALUE); - } - - @Override - public ByteBuf heapBuffer(int initialCapacity) { - return heapBuffer(initialCapacity, Integer.MAX_VALUE); - } - - @Override - public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) { - if (initialCapacity == 0 && maxCapacity == 0) { - return emptyBuf; - } - validate(initialCapacity, maxCapacity); - return newHeapBuffer(initialCapacity, maxCapacity); - } - - @Override - public ByteBuf directBuffer() { - return directBuffer(DEFAULT_INITIAL_CAPACITY, Integer.MAX_VALUE); - } - - @Override - public ByteBuf directBuffer(int initialCapacity) { - return directBuffer(initialCapacity, Integer.MAX_VALUE); - } - - @Override - public ByteBuf directBuffer(int initialCapacity, int maxCapacity) { - if (initialCapacity == 0 && maxCapacity == 0) { - return emptyBuf; - } - validate(initialCapacity, maxCapacity); - return newDirectBuffer(initialCapacity, maxCapacity); - } - - @Override - public CompositeByteBuf compositeBuffer() { - if (directByDefault) { - return compositeDirectBuffer(); - } - return compositeHeapBuffer(); - } - - @Override - public CompositeByteBuf compositeBuffer(int maxNumComponents) { - if (directByDefault) { - return compositeDirectBuffer(maxNumComponents); - } - return compositeHeapBuffer(maxNumComponents); - } - - @Override - public CompositeByteBuf compositeHeapBuffer() { - return compositeHeapBuffer(DEFAULT_MAX_COMPONENTS); - } - - @Override - public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) { - return new CompositeByteBuf(this, false, maxNumComponents); - } - - @Override - public CompositeByteBuf compositeDirectBuffer() { - return compositeDirectBuffer(DEFAULT_MAX_COMPONENTS); - } - - @Override - public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) { - return new CompositeByteBuf(this, true, maxNumComponents); - } - - private static void validate(int initialCapacity, int maxCapacity) { - if (initialCapacity < 0) { - throw new IllegalArgumentException("initialCapacity: " + initialCapacity + " (expectd: 0+)"); - } - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity: %d (expected: not greater than maxCapacity(%d)", - initialCapacity, maxCapacity)); - } - } - - /** - * Create a heap {@link ByteBuf} with the given initialCapacity and maxCapacity. - */ - protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity); - - /** - * Create a direct {@link ByteBuf} with the given initialCapacity and maxCapacity. - */ - protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity); - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + "(directByDefault: " + directByDefault + ')'; - } -} diff --git a/java/src/game/net/buffer/AbstractDerivedByteBuf.java b/java/src/game/net/buffer/AbstractDerivedByteBuf.java deleted file mode 100644 index 61b69e0..0000000 --- a/java/src/game/net/buffer/AbstractDerivedByteBuf.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.nio.ByteBuffer; - -/** - * Abstract base class for {@link ByteBuf} implementations that wrap another - * {@link ByteBuf}. - */ -public abstract class AbstractDerivedByteBuf extends AbstractByteBuf { - - protected AbstractDerivedByteBuf(int maxCapacity) { - super(maxCapacity); - } - - @Override - public final int refCnt() { - return unwrap().refCnt(); - } - - @Override - public final ByteBuf retain() { - unwrap().retain(); - return this; - } - - @Override - public final ByteBuf retain(int increment) { - unwrap().retain(increment); - return this; - } - - @Override - public final boolean release() { - return unwrap().release(); - } - - @Override - public final boolean release(int decrement) { - return unwrap().release(decrement); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return unwrap().nioBuffer(index, length); - } -} diff --git a/java/src/game/net/buffer/AbstractReferenceCountedByteBuf.java b/java/src/game/net/buffer/AbstractReferenceCountedByteBuf.java deleted file mode 100644 index a398bc9..0000000 --- a/java/src/game/net/buffer/AbstractReferenceCountedByteBuf.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import game.net.util.IllegalReferenceCountException; -import game.net.util.internal.PlatformDependent; - -/** - * Abstract base class for {@link ByteBuf} implementations that count references. - */ -public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf { - - private static final AtomicIntegerFieldUpdater refCntUpdater; - - static { - AtomicIntegerFieldUpdater updater = - PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCountedByteBuf.class, "refCnt"); - if (updater == null) { - updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt"); - } - refCntUpdater = updater; - } - - private volatile int refCnt = 1; - - protected AbstractReferenceCountedByteBuf(int maxCapacity) { - super(maxCapacity); - } - - @Override - public final int refCnt() { - return refCnt; - } - - /** - * An unsafe operation intended for use by a subclass that sets the reference count of the buffer directly - */ - protected final void setRefCnt(int refCnt) { - this.refCnt = refCnt; - } - - @Override - public ByteBuf retain() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, 1); - } - if (refCnt == Integer.MAX_VALUE) { - throw new IllegalReferenceCountException(Integer.MAX_VALUE, 1); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + 1)) { - break; - } - } - return this; - } - - @Override - public ByteBuf retain(int increment) { - if (increment <= 0) { - throw new IllegalArgumentException("increment: " + increment + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, increment); - } - if (refCnt > Integer.MAX_VALUE - increment) { - throw new IllegalReferenceCountException(refCnt, increment); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + increment)) { - break; - } - } - return this; - } - - @Override - public final boolean release() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, -1); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - 1)) { - if (refCnt == 1) { - deallocate(); - return true; - } - return false; - } - } - } - - @Override - public final boolean release(int decrement) { - if (decrement <= 0) { - throw new IllegalArgumentException("decrement: " + decrement + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt < decrement) { - throw new IllegalReferenceCountException(refCnt, -decrement); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) { - if (refCnt == decrement) { - deallocate(); - return true; - } - return false; - } - } - } - - /** - * Called once {@link #refCnt()} is equals 0. - */ - protected abstract void deallocate(); -} diff --git a/java/src/game/net/buffer/AdvancedLeakAwareByteBuf.java b/java/src/game/net/buffer/AdvancedLeakAwareByteBuf.java deleted file mode 100644 index da66af7..0000000 --- a/java/src/game/net/buffer/AdvancedLeakAwareByteBuf.java +++ /dev/null @@ -1,724 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import game.net.util.ResourceLeak; - -final class AdvancedLeakAwareByteBuf extends WrappedByteBuf { - - private final ResourceLeak leak; - - AdvancedLeakAwareByteBuf(ByteBuf buf, ResourceLeak leak) { - super(buf); - this.leak = leak; - } - - @Override - public boolean release() { - boolean deallocated = super.release(); - if (deallocated) { - leak.close(); - } else { - leak.record(); - } - return deallocated; - } - - @Override - public boolean release(int decrement) { - boolean deallocated = super.release(decrement); - if (deallocated) { - leak.close(); - } else { - leak.record(); - } - return deallocated; - } - - @Override - public ByteBuf order(ByteOrder endianness) { - leak.record(); - if (order() == endianness) { - return this; - } else { - return new AdvancedLeakAwareByteBuf(super.order(endianness), leak); - } - } - - @Override - public ByteBuf slice() { - leak.record(); - return new AdvancedLeakAwareByteBuf(super.slice(), leak); - } - - @Override - public ByteBuf slice(int index, int length) { - leak.record(); - return new AdvancedLeakAwareByteBuf(super.slice(index, length), leak); - } - - @Override - public ByteBuf duplicate() { - leak.record(); - return new AdvancedLeakAwareByteBuf(super.duplicate(), leak); - } - - @Override - public ByteBuf readSlice(int length) { - leak.record(); - return new AdvancedLeakAwareByteBuf(super.readSlice(length), leak); - } - - @Override - public ByteBuf discardReadBytes() { - leak.record(); - return super.discardReadBytes(); - } - - @Override - public ByteBuf discardSomeReadBytes() { - leak.record(); - return super.discardSomeReadBytes(); - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - leak.record(); - return super.ensureWritable(minWritableBytes); - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - leak.record(); - return super.ensureWritable(minWritableBytes, force); - } - - @Override - public boolean getBoolean(int index) { - leak.record(); - return super.getBoolean(index); - } - - @Override - public byte getByte(int index) { - leak.record(); - return super.getByte(index); - } - - @Override - public short getUnsignedByte(int index) { - leak.record(); - return super.getUnsignedByte(index); - } - - @Override - public short getShort(int index) { - leak.record(); - return super.getShort(index); - } - - @Override - public int getUnsignedShort(int index) { - leak.record(); - return super.getUnsignedShort(index); - } - - @Override - public int getMedium(int index) { - leak.record(); - return super.getMedium(index); - } - - @Override - public int getUnsignedMedium(int index) { - leak.record(); - return super.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - leak.record(); - return super.getInt(index); - } - - @Override - public long getUnsignedInt(int index) { - leak.record(); - return super.getUnsignedInt(index); - } - - @Override - public long getLong(int index) { - leak.record(); - return super.getLong(index); - } - - @Override - public char getChar(int index) { - leak.record(); - return super.getChar(index); - } - - @Override - public float getFloat(int index) { - leak.record(); - return super.getFloat(index); - } - - @Override - public double getDouble(int index) { - leak.record(); - return super.getDouble(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - leak.record(); - return super.getBytes(index, dst); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - leak.record(); - return super.getBytes(index, dst, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - leak.record(); - return super.getBytes(index, dst, dstIndex, length); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - leak.record(); - return super.getBytes(index, dst); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - leak.record(); - return super.getBytes(index, dst, dstIndex, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - leak.record(); - return super.getBytes(index, dst); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - leak.record(); - return super.getBytes(index, out, length); - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - leak.record(); - return super.getBytes(index, out, length); - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - leak.record(); - return super.setBoolean(index, value); - } - - @Override - public ByteBuf setByte(int index, int value) { - leak.record(); - return super.setByte(index, value); - } - - @Override - public ByteBuf setShort(int index, int value) { - leak.record(); - return super.setShort(index, value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - leak.record(); - return super.setMedium(index, value); - } - - @Override - public ByteBuf setInt(int index, int value) { - leak.record(); - return super.setInt(index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - leak.record(); - return super.setLong(index, value); - } - - @Override - public ByteBuf setChar(int index, int value) { - leak.record(); - return super.setChar(index, value); - } - - @Override - public ByteBuf setFloat(int index, float value) { - leak.record(); - return super.setFloat(index, value); - } - - @Override - public ByteBuf setDouble(int index, double value) { - leak.record(); - return super.setDouble(index, value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - leak.record(); - return super.setBytes(index, src); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - leak.record(); - return super.setBytes(index, src, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - leak.record(); - return super.setBytes(index, src, srcIndex, length); - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - leak.record(); - return super.setBytes(index, src); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - leak.record(); - return super.setBytes(index, src, srcIndex, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - leak.record(); - return super.setBytes(index, src); - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - leak.record(); - return super.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - leak.record(); - return super.setBytes(index, in, length); - } - - @Override - public ByteBuf setZero(int index, int length) { - leak.record(); - return super.setZero(index, length); - } - - @Override - public boolean readBoolean() { - leak.record(); - return super.readBoolean(); - } - - @Override - public byte readByte() { - leak.record(); - return super.readByte(); - } - - @Override - public short readUnsignedByte() { - leak.record(); - return super.readUnsignedByte(); - } - - @Override - public short readShort() { - leak.record(); - return super.readShort(); - } - - @Override - public int readUnsignedShort() { - leak.record(); - return super.readUnsignedShort(); - } - - @Override - public int readMedium() { - leak.record(); - return super.readMedium(); - } - - @Override - public int readUnsignedMedium() { - leak.record(); - return super.readUnsignedMedium(); - } - - @Override - public int readInt() { - leak.record(); - return super.readInt(); - } - - @Override - public long readUnsignedInt() { - leak.record(); - return super.readUnsignedInt(); - } - - @Override - public long readLong() { - leak.record(); - return super.readLong(); - } - - @Override - public char readChar() { - leak.record(); - return super.readChar(); - } - - @Override - public float readFloat() { - leak.record(); - return super.readFloat(); - } - - @Override - public double readDouble() { - leak.record(); - return super.readDouble(); - } - - @Override - public ByteBuf readBytes(int length) { - leak.record(); - return super.readBytes(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - leak.record(); - return super.readBytes(dst); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - leak.record(); - return super.readBytes(dst, length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - leak.record(); - return super.readBytes(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(byte[] dst) { - leak.record(); - return super.readBytes(dst); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - leak.record(); - return super.readBytes(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - leak.record(); - return super.readBytes(dst); - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - leak.record(); - return super.readBytes(out, length); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - leak.record(); - return super.readBytes(out, length); - } - - @Override - public ByteBuf skipBytes(int length) { - leak.record(); - return super.skipBytes(length); - } - - @Override - public ByteBuf writeBoolean(boolean value) { - leak.record(); - return super.writeBoolean(value); - } - - @Override - public ByteBuf writeByte(int value) { - leak.record(); - return super.writeByte(value); - } - - @Override - public ByteBuf writeShort(int value) { - leak.record(); - return super.writeShort(value); - } - - @Override - public ByteBuf writeMedium(int value) { - leak.record(); - return super.writeMedium(value); - } - - @Override - public ByteBuf writeInt(int value) { - leak.record(); - return super.writeInt(value); - } - - @Override - public ByteBuf writeLong(long value) { - leak.record(); - return super.writeLong(value); - } - - @Override - public ByteBuf writeChar(int value) { - leak.record(); - return super.writeChar(value); - } - - @Override - public ByteBuf writeFloat(float value) { - leak.record(); - return super.writeFloat(value); - } - - @Override - public ByteBuf writeDouble(double value) { - leak.record(); - return super.writeDouble(value); - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - leak.record(); - return super.writeBytes(src); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - leak.record(); - return super.writeBytes(src, length); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - leak.record(); - return super.writeBytes(src, srcIndex, length); - } - - @Override - public ByteBuf writeBytes(byte[] src) { - leak.record(); - return super.writeBytes(src); - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - leak.record(); - return super.writeBytes(src, srcIndex, length); - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - leak.record(); - return super.writeBytes(src); - } - - @Override - public int writeBytes(InputStream in, int length) throws IOException { - leak.record(); - return super.writeBytes(in, length); - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - leak.record(); - return super.writeBytes(in, length); - } - - @Override - public ByteBuf writeZero(int length) { - leak.record(); - return super.writeZero(length); - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - leak.record(); - return super.indexOf(fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - leak.record(); - return super.bytesBefore(value); - } - - @Override - public int bytesBefore(int length, byte value) { - leak.record(); - return super.bytesBefore(length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - leak.record(); - return super.bytesBefore(index, length, value); - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - leak.record(); - return super.forEachByte(processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - leak.record(); - return super.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - leak.record(); - return super.forEachByteDesc(processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - leak.record(); - return super.forEachByteDesc(index, length, processor); - } - - @Override - public ByteBuf copy() { - leak.record(); - return super.copy(); - } - - @Override - public ByteBuf copy(int index, int length) { - leak.record(); - return super.copy(index, length); - } - - @Override - public int nioBufferCount() { - leak.record(); - return super.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer() { - leak.record(); - return super.nioBuffer(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - leak.record(); - return super.nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers() { - leak.record(); - return super.nioBuffers(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - leak.record(); - return super.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - leak.record(); - return super.internalNioBuffer(index, length); - } - - @Override - public String toString(Charset charset) { - leak.record(); - return super.toString(charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - leak.record(); - return super.toString(index, length, charset); - } - - @Override - public ByteBuf retain() { - leak.record(); - return super.retain(); - } - - @Override - public ByteBuf retain(int increment) { - leak.record(); - return super.retain(increment); - } - - @Override - public ByteBuf capacity(int newCapacity) { - leak.record(); - return super.capacity(newCapacity); - } -} diff --git a/java/src/game/net/buffer/ByteBuf.java b/java/src/game/net/buffer/ByteBuf.java deleted file mode 100644 index 61c085c..0000000 --- a/java/src/game/net/buffer/ByteBuf.java +++ /dev/null @@ -1,1879 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import game.net.util.ReferenceCounted; - -/** - * A random and sequential accessible sequence of zero or more bytes (octets). - * This interface provides an abstract view for one or more primitive byte - * arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}. - * - *

Creation of a buffer

- * - * It is recommended to create a new buffer using the helper methods in - * {@link Unpooled} rather than calling an individual implementation's - * constructor. - * - *

Random Access Indexing

- * - * Just like an ordinary primitive byte array, {@link ByteBuf} uses - * zero-based indexing. - * It means the index of the first byte is always {@code 0} and the index of the last byte is - * always {@link #capacity() capacity - 1}. For example, to iterate all bytes of a buffer, you - * can do the following, regardless of its internal implementation: - * - *
- * {@link ByteBuf} buffer = ...;
- * for (int i = 0; i < buffer.capacity(); i ++) {
- *     byte b = buffer.getByte(i);
- *     System.out.println((char) b);
- * }
- * 
- * - *

Sequential Access Indexing

- * - * {@link ByteBuf} provides two pointer variables to support sequential - * read and write operations - {@link #readerIndex() readerIndex} for a read - * operation and {@link #writerIndex() writerIndex} for a write operation - * respectively. The following diagram shows how a buffer is segmented into - * three areas by the two pointers: - * - *
- *      +-------------------+------------------+------------------+
- *      | discardable bytes |  readable bytes  |  writable bytes  |
- *      |                   |     (CONTENT)    |                  |
- *      +-------------------+------------------+------------------+
- *      |                   |                  |                  |
- *      0      <=      readerIndex   <=   writerIndex    <=    capacity
- * 
- * - *

Readable bytes (the actual content)

- * - * This segment is where the actual data is stored. Any operation whose name - * starts with {@code read} or {@code skip} will get or skip the data at the - * current {@link #readerIndex() readerIndex} and increase it by the number of - * read bytes. If the argument of the read operation is also a - * {@link ByteBuf} and no destination index is specified, the specified - * buffer's {@link #writerIndex() writerIndex} is increased together. - *

- * If there's not enough content left, {@link IndexOutOfBoundsException} is - * raised. The default value of newly allocated, wrapped or copied buffer's - * {@link #readerIndex() readerIndex} is {@code 0}. - * - *

- * // Iterates the readable bytes of a buffer.
- * {@link ByteBuf} buffer = ...;
- * while (buffer.readable()) {
- *     System.out.println(buffer.readByte());
- * }
- * 
- * - *

Writable bytes

- * - * This segment is a undefined space which needs to be filled. Any operation - * whose name ends with {@code write} will write the data at the current - * {@link #writerIndex() writerIndex} and increase it by the number of written - * bytes. If the argument of the write operation is also a {@link ByteBuf}, - * and no source index is specified, the specified buffer's - * {@link #readerIndex() readerIndex} is increased together. - *

- * If there's not enough writable bytes left, {@link IndexOutOfBoundsException} - * is raised. The default value of newly allocated buffer's - * {@link #writerIndex() writerIndex} is {@code 0}. The default value of - * wrapped or copied buffer's {@link #writerIndex() writerIndex} is the - * {@link #capacity() capacity} of the buffer. - * - *

- * // Fills the writable bytes of a buffer with random integers.
- * {@link ByteBuf} buffer = ...;
- * while (buffer.maxWritableBytes() >= 4) {
- *     buffer.writeInt(random.nextInt());
- * }
- * 
- * - *

Discardable bytes

- * - * This segment contains the bytes which were read already by a read operation. - * Initially, the size of this segment is {@code 0}, but its size increases up - * to the {@link #writerIndex() writerIndex} as read operations are executed. - * The read bytes can be discarded by calling {@link #discardReadBytes()} to - * reclaim unused area as depicted by the following diagram: - * - *
- *  BEFORE discardReadBytes()
- *
- *      +-------------------+------------------+------------------+
- *      | discardable bytes |  readable bytes  |  writable bytes  |
- *      +-------------------+------------------+------------------+
- *      |                   |                  |                  |
- *      0      <=      readerIndex   <=   writerIndex    <=    capacity
- *
- *
- *  AFTER discardReadBytes()
- *
- *      +------------------+--------------------------------------+
- *      |  readable bytes  |    writable bytes (got more space)   |
- *      +------------------+--------------------------------------+
- *      |                  |                                      |
- * readerIndex (0) <= writerIndex (decreased)        <=        capacity
- * 
- * - * Please note that there is no guarantee about the content of writable bytes - * after calling {@link #discardReadBytes()}. The writable bytes will not be - * moved in most cases and could even be filled with completely different data - * depending on the underlying buffer implementation. - * - *

Clearing the buffer indexes

- * - * You can set both {@link #readerIndex() readerIndex} and - * {@link #writerIndex() writerIndex} to {@code 0} by calling {@link #clear()}. - * It does not clear the buffer content (e.g. filling with {@code 0}) but just - * clears the two pointers. Please also note that the semantic of this - * operation is different from {@link ByteBuffer#clear()}. - * - *
- *  BEFORE clear()
- *
- *      +-------------------+------------------+------------------+
- *      | discardable bytes |  readable bytes  |  writable bytes  |
- *      +-------------------+------------------+------------------+
- *      |                   |                  |                  |
- *      0      <=      readerIndex   <=   writerIndex    <=    capacity
- *
- *
- *  AFTER clear()
- *
- *      +---------------------------------------------------------+
- *      |             writable bytes (got more space)             |
- *      +---------------------------------------------------------+
- *      |                                                         |
- *      0 = readerIndex = writerIndex            <=            capacity
- * 
- * - *

Search operations

- * - * For simple single-byte searches, use {@link #indexOf(int, int, byte)} and {@link #bytesBefore(int, int, byte)}. - * {@link #bytesBefore(byte)} is especially useful when you deal with a {@code NUL}-terminated string. - * For complicated searches, use {@link #forEachByte(int, int, ByteBufProcessor)} with a {@link ByteBufProcessor} - * implementation. - * - *

Mark and reset

- * - * There are two marker indexes in every buffer. One is for storing - * {@link #readerIndex() readerIndex} and the other is for storing - * {@link #writerIndex() writerIndex}. You can always reposition one of the - * two indexes by calling a reset method. It works in a similar fashion to - * the mark and reset methods in {@link InputStream} except that there's no - * {@code readlimit}. - * - *

Derived buffers

- * - * You can create a view of an existing buffer by calling either - * {@link #duplicate()}, {@link #slice()} or {@link #slice(int, int)}. - * A derived buffer will have an independent {@link #readerIndex() readerIndex}, - * {@link #writerIndex() writerIndex} and marker indexes, while it shares - * other internal data representation, just like a NIO buffer does. - *

- * In case a completely fresh copy of an existing buffer is required, please - * call {@link #copy()} method instead. - * - *

Conversion to existing JDK types

- * - *

Byte array

- * - * If a {@link ByteBuf} is backed by a byte array (i.e. {@code byte[]}), - * you can access it directly via the {@link #array()} method. To determine - * if a buffer is backed by a byte array, {@link #hasArray()} should be used. - * - *

NIO Buffers

- * - * If a {@link ByteBuf} can be converted into an NIO {@link ByteBuffer} which shares its - * content (i.e. view buffer), you can get it via the {@link #nioBuffer()} method. To determine - * if a buffer can be converted into an NIO buffer, use {@link #nioBufferCount()}. - * - *

Strings

- * - * Various {@link #toString(Charset)} methods convert a {@link ByteBuf} - * into a {@link String}. Please note that {@link #toString()} is not a - * conversion method. - * - *

I/O Streams

- * - * Please refer to {@link ByteBufInputStream} and - * {@link ByteBufOutputStream}. - */ - -public abstract class ByteBuf implements ReferenceCounted, Comparable { - - /** - * Returns the number of bytes (octets) this buffer can contain. - */ - public abstract int capacity(); - - /** - * Adjusts the capacity of this buffer. If the {@code newCapacity} is less than the current - * capacity, the content of this buffer is truncated. If the {@code newCapacity} is greater - * than the current capacity, the buffer is appended with unspecified data whose length is - * {@code (newCapacity - currentCapacity)}. - */ - public abstract ByteBuf capacity(int newCapacity); - - /** - * Returns the maximum allowed capacity of this buffer. If a user attempts to increase the - * capacity of this buffer beyond the maximum capacity using {@link #capacity(int)} or - * {@link #ensureWritable(int)}, those methods will raise an - * {@link IllegalArgumentException}. - */ - public abstract int maxCapacity(); - - /** - * Returns the {@link ByteBufAllocator} which created this buffer. - */ - public abstract ByteBufAllocator alloc(); - - /** - * Returns the endianness - * of this buffer. - */ - public abstract ByteOrder order(); - - /** - * Returns a buffer with the specified {@code endianness} which shares the whole region, - * indexes, and marks of this buffer. Modifying the content, the indexes, or the marks of the - * returned buffer or this buffer affects each other's content, indexes, and marks. If the - * specified {@code endianness} is identical to this buffer's byte order, this method can - * return {@code this}. This method does not modify {@code readerIndex} or {@code writerIndex} - * of this buffer. - */ - public abstract ByteBuf order(ByteOrder endianness); - - /** - * Return the underlying buffer instance if this buffer is a wrapper of another buffer. - * - * @return {@code null} if this buffer is not a wrapper - */ - public abstract ByteBuf unwrap(); - - /** - * Returns {@code true} if and only if this buffer is backed by an - * NIO direct buffer. - */ - public abstract boolean isDirect(); - - /** - * Returns the {@code readerIndex} of this buffer. - */ - public abstract int readerIndex(); - - /** - * Sets the {@code readerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code readerIndex} is - * less than {@code 0} or - * greater than {@code this.writerIndex} - */ - public abstract ByteBuf readerIndex(int readerIndex); - - /** - * Returns the {@code writerIndex} of this buffer. - */ - public abstract int writerIndex(); - - /** - * Sets the {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code writerIndex} is - * less than {@code this.readerIndex} or - * greater than {@code this.capacity} - */ - public abstract ByteBuf writerIndex(int writerIndex); - - /** - * Sets the {@code readerIndex} and {@code writerIndex} of this buffer - * in one shot. This method is useful when you have to worry about the - * invocation order of {@link #readerIndex(int)} and {@link #writerIndex(int)} - * methods. For example, the following code will fail: - * - *
-     * // Create a buffer whose readerIndex, writerIndex and capacity are
-     * // 0, 0 and 8 respectively.
-     * {@link ByteBuf} buf = {@link Unpooled}.buffer(8);
-     *
-     * // IndexOutOfBoundsException is thrown because the specified
-     * // readerIndex (2) cannot be greater than the current writerIndex (0).
-     * buf.readerIndex(2);
-     * buf.writerIndex(4);
-     * 
- * - * The following code will also fail: - * - *
-     * // Create a buffer whose readerIndex, writerIndex and capacity are
-     * // 0, 8 and 8 respectively.
-     * {@link ByteBuf} buf = {@link Unpooled}.wrappedBuffer(new byte[8]);
-     *
-     * // readerIndex becomes 8.
-     * buf.readLong();
-     *
-     * // IndexOutOfBoundsException is thrown because the specified
-     * // writerIndex (4) cannot be less than the current readerIndex (8).
-     * buf.writerIndex(4);
-     * buf.readerIndex(2);
-     * 
- * - * By contrast, this method guarantees that it never - * throws an {@link IndexOutOfBoundsException} as long as the specified - * indexes meet basic constraints, regardless what the current index - * values of the buffer are: - * - *
-     * // No matter what the current state of the buffer is, the following
-     * // call always succeeds as long as the capacity of the buffer is not
-     * // less than 4.
-     * buf.setIndex(2, 4);
-     * 
- * - * @throws IndexOutOfBoundsException - * if the specified {@code readerIndex} is less than 0, - * if the specified {@code writerIndex} is less than the specified - * {@code readerIndex} or if the specified {@code writerIndex} is - * greater than {@code this.capacity} - */ - public abstract ByteBuf setIndex(int readerIndex, int writerIndex); - - /** - * Returns the number of readable bytes which is equal to - * {@code (this.writerIndex - this.readerIndex)}. - */ - public abstract int readableBytes(); - - /** - * Returns the number of writable bytes which is equal to - * {@code (this.capacity - this.writerIndex)}. - */ - public abstract int writableBytes(); - - /** - * Returns the maximum possible number of writable bytes, which is equal to - * {@code (this.maxCapacity - this.writerIndex)}. - */ - public abstract int maxWritableBytes(); - - /** - * Returns {@code true} - * if and only if {@code (this.writerIndex - this.readerIndex)} is greater - * than {@code 0}. - */ - public abstract boolean isReadable(); - - /** - * Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements. - */ - public abstract boolean isReadable(int size); - - /** - * Returns {@code true} - * if and only if {@code (this.capacity - this.writerIndex)} is greater - * than {@code 0}. - */ - public abstract boolean isWritable(); - - /** - * Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of - * elements. - */ - public abstract boolean isWritable(int size); - - /** - * Sets the {@code readerIndex} and {@code writerIndex} of this buffer to - * {@code 0}. - * This method is identical to {@link #setIndex(int, int) setIndex(0, 0)}. - *

- * Please note that the behavior of this method is different - * from that of NIO buffer, which sets the {@code limit} to - * the {@code capacity} of the buffer. - */ - public abstract ByteBuf clear(); - - /** - * Marks the current {@code readerIndex} in this buffer. You can - * reposition the current {@code readerIndex} to the marked - * {@code readerIndex} by calling {@link #resetReaderIndex()}. - * The initial value of the marked {@code readerIndex} is {@code 0}. - */ - public abstract ByteBuf markReaderIndex(); - - /** - * Repositions the current {@code readerIndex} to the marked - * {@code readerIndex} in this buffer. - * - * @throws IndexOutOfBoundsException - * if the current {@code writerIndex} is less than the marked - * {@code readerIndex} - */ - public abstract ByteBuf resetReaderIndex(); - - /** - * Marks the current {@code writerIndex} in this buffer. You can - * reposition the current {@code writerIndex} to the marked - * {@code writerIndex} by calling {@link #resetWriterIndex()}. - * The initial value of the marked {@code writerIndex} is {@code 0}. - */ - public abstract ByteBuf markWriterIndex(); - - /** - * Repositions the current {@code writerIndex} to the marked - * {@code writerIndex} in this buffer. - * - * @throws IndexOutOfBoundsException - * if the current {@code readerIndex} is greater than the marked - * {@code writerIndex} - */ - public abstract ByteBuf resetWriterIndex(); - - /** - * Discards the bytes between the 0th index and {@code readerIndex}. - * It moves the bytes between {@code readerIndex} and {@code writerIndex} - * to the 0th index, and sets {@code readerIndex} and {@code writerIndex} - * to {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively. - *

- * Please refer to the class documentation for more detailed explanation. - */ - public abstract ByteBuf discardReadBytes(); - - /** - * Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard - * some, all, or none of read bytes depending on its internal implementation to reduce - * overall memory bandwidth consumption at the cost of potentially additional memory - * consumption. - */ - public abstract ByteBuf discardSomeReadBytes(); - - /** - * Makes sure the number of {@linkplain #writableBytes() the writable bytes} - * is equal to or greater than the specified value. If there is enough - * writable bytes in this buffer, this method returns with no side effect. - * Otherwise, it raises an {@link IllegalArgumentException}. - * - * @param minWritableBytes - * the expected minimum number of writable bytes - * @throws IndexOutOfBoundsException - * if {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()} - */ - public abstract ByteBuf ensureWritable(int minWritableBytes); - - /** - * Tries to make sure the number of {@linkplain #writableBytes() the writable bytes} - * is equal to or greater than the specified value. Unlike {@link #ensureWritable(int)}, - * this method does not raise an exception but returns a code. - * - * @param minWritableBytes - * the expected minimum number of writable bytes - * @param force - * When {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}: - *

    - *
  • {@code true} - the capacity of the buffer is expanded to {@link #maxCapacity()}
  • - *
  • {@code false} - the capacity of the buffer is unchanged
  • - *
- * @return {@code 0} if the buffer has enough writable bytes, and its capacity is unchanged. - * {@code 1} if the buffer does not have enough bytes, and its capacity is unchanged. - * {@code 2} if the buffer has enough writable bytes, and its capacity has been increased. - * {@code 3} if the buffer does not have enough bytes, but its capacity has been - * increased to its maximum. - */ - public abstract int ensureWritable(int minWritableBytes, boolean force); - - /** - * Gets a boolean at the specified absolute (@code index) in this buffer. - * This method does not modify the {@code readerIndex} or {@code writerIndex} - * of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract boolean getBoolean(int index); - - /** - * Gets a byte at the specified absolute {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract byte getByte(int index); - - /** - * Gets an unsigned byte at the specified absolute {@code index} in this - * buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract short getUnsignedByte(int index); - - /** - * Gets a 16-bit short integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract short getShort(int index); - - /** - * Gets an unsigned 16-bit short integer at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract int getUnsignedShort(int index); - - /** - * Gets a 24-bit medium integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 3} is greater than {@code this.capacity} - */ - public abstract int getMedium(int index); - - /** - * Gets an unsigned 24-bit medium integer at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 3} is greater than {@code this.capacity} - */ - public abstract int getUnsignedMedium(int index); - - /** - * Gets a 32-bit integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract int getInt(int index); - - /** - * Gets an unsigned 32-bit integer at the specified absolute {@code index} - * in this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract long getUnsignedInt(int index); - - /** - * Gets a 64-bit long integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract long getLong(int index); - - /** - * Gets a 2-byte UTF-16 character at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract char getChar(int index); - - /** - * Gets a 32-bit floating point number at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract float getFloat(int index); - - /** - * Gets a 64-bit floating point number at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract double getDouble(int index); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index} until the destination becomes - * non-writable. This method is basically same with - * {@link #getBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code writerIndex} of the destination by the - * number of the transferred bytes while - * {@link #getBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + dst.writableBytes} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf getBytes(int index, ByteBuf dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. This method is basically same - * with {@link #getBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code writerIndex} of the destination by the - * number of the transferred bytes while - * {@link #getBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code length} is greater than {@code dst.writableBytes} - */ - public abstract ByteBuf getBytes(int index, ByteBuf dst, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} - * of both the source (i.e. {@code this}) and the destination. - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code dstIndex + length} is greater than - * {@code dst.capacity} - */ - public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + dst.length} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf getBytes(int index, byte[] dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} - * of this buffer. - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code dstIndex + length} is greater than - * {@code dst.length} - */ - public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index} until the destination's position - * reaches its limit. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer while the destination's {@code position} will be increased. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + dst.remaining()} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf getBytes(int index, ByteBuffer dst); - - /** - * Transfers this buffer's data to the specified stream starting at the - * specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than - * {@code this.capacity} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException; - - /** - * Transfers this buffer's data to the specified channel starting at the - * specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes written out to the specified channel - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than - * {@code this.capacity} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException; - - /** - * Sets the specified boolean at the specified absolute {@code index} in this - * buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract ByteBuf setBoolean(int index, boolean value); - - /** - * Sets the specified byte at the specified absolute {@code index} in this - * buffer. The 24 high-order bits of the specified value are ignored. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract ByteBuf setByte(int index, int value); - - /** - * Sets the specified 16-bit short integer at the specified absolute - * {@code index} in this buffer. The 16 high-order bits of the specified - * value are ignored. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract ByteBuf setShort(int index, int value); - - /** - * Sets the specified 24-bit medium integer at the specified absolute - * {@code index} in this buffer. Please note that the most significant - * byte is ignored in the specified value. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 3} is greater than {@code this.capacity} - */ - public abstract ByteBuf setMedium(int index, int value); - - /** - * Sets the specified 32-bit integer at the specified absolute - * {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract ByteBuf setInt(int index, int value); - - /** - * Sets the specified 64-bit long integer at the specified absolute - * {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract ByteBuf setLong(int index, long value); - - /** - * Sets the specified 2-byte UTF-16 character at the specified absolute - * {@code index} in this buffer. - * The 16 high-order bits of the specified value are ignored. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract ByteBuf setChar(int index, int value); - - /** - * Sets the specified 32-bit floating-point number at the specified - * absolute {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract ByteBuf setFloat(int index, float value); - - /** - * Sets the specified 64-bit floating-point number at the specified - * absolute {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract ByteBuf setDouble(int index, double value); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index} until the source buffer becomes - * unreadable. This method is basically same with - * {@link #setBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code readerIndex} of the source buffer by - * the number of the transferred bytes while - * {@link #setBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + src.readableBytes} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf setBytes(int index, ByteBuf src); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index}. This method is basically same - * with {@link #setBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code readerIndex} of the source buffer by - * the number of the transferred bytes while - * {@link #setBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code length} is greater than {@code src.readableBytes} - */ - public abstract ByteBuf setBytes(int index, ByteBuf src, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} - * of both the source (i.e. {@code this}) and the destination. - * - * @param srcIndex the first index of the source - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code srcIndex + length} is greater than - * {@code src.capacity} - */ - public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length); - - /** - * Transfers the specified source array's data to this buffer starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + src.length} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf setBytes(int index, byte[] src); - - /** - * Transfers the specified source array's data to this buffer starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code srcIndex + length} is greater than {@code src.length} - */ - public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index} until the source buffer's position - * reaches its limit. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + src.remaining()} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf setBytes(int index, ByteBuffer src); - - /** - * Transfers the content of the specified source stream to this buffer - * starting at the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the number of bytes to transfer - * - * @return the actual number of bytes read in from the specified channel. - * {@code -1} if the specified channel is closed. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than {@code this.capacity} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract int setBytes(int index, InputStream in, int length) throws IOException; - - /** - * Transfers the content of the specified source channel to this buffer - * starting at the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes read in from the specified channel. - * {@code -1} if the specified channel is closed. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than {@code this.capacity} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException; - - /** - * Fills this buffer with NUL (0x00) starting at the specified - * absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the number of NULs to write to the buffer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than {@code this.capacity} - */ - public abstract ByteBuf setZero(int index, int length); - - /** - * Gets a boolean at the current {@code readerIndex} and increases - * the {@code readerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 1} - */ - public abstract boolean readBoolean(); - - /** - * Gets a byte at the current {@code readerIndex} and increases - * the {@code readerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 1} - */ - public abstract byte readByte(); - - /** - * Gets an unsigned byte at the current {@code readerIndex} and increases - * the {@code readerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 1} - */ - public abstract short readUnsignedByte(); - - /** - * Gets a 16-bit short integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 2} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 2} - */ - public abstract short readShort(); - - /** - * Gets an unsigned 16-bit short integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 2} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 2} - */ - public abstract int readUnsignedShort(); - - /** - * Gets a 24-bit medium integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 3} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 3} - */ - public abstract int readMedium(); - - /** - * Gets an unsigned 24-bit medium integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 3} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 3} - */ - public abstract int readUnsignedMedium(); - - /** - * Gets a 32-bit integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 4} - */ - public abstract int readInt(); - - /** - * Gets an unsigned 32-bit integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 4} - */ - public abstract long readUnsignedInt(); - - /** - * Gets a 64-bit integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 8} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 8} - */ - public abstract long readLong(); - - /** - * Gets a 2-byte UTF-16 character at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 2} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 2} - */ - public abstract char readChar(); - - /** - * Gets a 32-bit floating point number at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 4} - */ - public abstract float readFloat(); - - /** - * Gets a 64-bit floating point number at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 8} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 8} - */ - public abstract double readDouble(); - - /** - * Transfers this buffer's data to a newly created buffer starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). - * The returned buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and {@code length} respectively. - * - * @param length the number of bytes to transfer - * - * @return the newly created buffer which contains the transferred bytes - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(int length); - - /** - * Returns a new slice of this buffer's sub-region starting at the current - * {@code readerIndex} and increases the {@code readerIndex} by the size - * of the new slice (= {@code length}). - * - * @param length the size of the new slice - * - * @return the newly created slice - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf readSlice(int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} until the destination becomes - * non-writable, and increases the {@code readerIndex} by the number of the - * transferred bytes. This method is basically same with - * {@link #readBytes(ByteBuf, int, int)}, except that this method - * increases the {@code writerIndex} of the destination by the number of - * the transferred bytes while {@link #readBytes(ByteBuf, int, int)} - * does not. - * - * @throws IndexOutOfBoundsException - * if {@code dst.writableBytes} is greater than - * {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(ByteBuf dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). This method - * is basically same with {@link #readBytes(ByteBuf, int, int)}, - * except that this method increases the {@code writerIndex} of the - * destination by the number of the transferred bytes (= {@code length}) - * while {@link #readBytes(ByteBuf, int, int)} does not. - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} or - * if {@code length} is greater than {@code dst.writableBytes} - */ - public abstract ByteBuf readBytes(ByteBuf dst, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code length} is greater than {@code this.readableBytes}, or - * if {@code dstIndex + length} is greater than - * {@code dst.capacity} - */ - public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code dst.length}). - * - * @throws IndexOutOfBoundsException - * if {@code dst.length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(byte[] dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code length} is greater than {@code this.readableBytes}, or - * if {@code dstIndex + length} is greater than {@code dst.length} - */ - public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} until the destination's position - * reaches its limit, and increases the {@code readerIndex} by the - * number of the transferred bytes. - * - * @throws IndexOutOfBoundsException - * if {@code dst.remaining()} is greater than - * {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(ByteBuffer dst); - - /** - * Transfers this buffer's data to the specified stream starting at the - * current {@code readerIndex}. - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException; - - /** - * Transfers this buffer's data to the specified stream starting at the - * current {@code readerIndex}. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes written out to the specified channel - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int readBytes(GatheringByteChannel out, int length) throws IOException; - - /** - * Increases the current {@code readerIndex} by the specified - * {@code length} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf skipBytes(int length); - - /** - * Sets the specified boolean at the current {@code writerIndex} - * and increases the {@code writerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 1} - */ - public abstract ByteBuf writeBoolean(boolean value); - - /** - * Sets the specified byte at the current {@code writerIndex} - * and increases the {@code writerIndex} by {@code 1} in this buffer. - * The 24 high-order bits of the specified value are ignored. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 1} - */ - public abstract ByteBuf writeByte(int value); - - /** - * Sets the specified 16-bit short integer at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} - * in this buffer. The 16 high-order bits of the specified value are ignored. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 2} - */ - public abstract ByteBuf writeShort(int value); - - /** - * Sets the specified 24-bit medium integer at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 3} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 3} - */ - public abstract ByteBuf writeMedium(int value); - - /** - * Sets the specified 32-bit integer at the current {@code writerIndex} - * and increases the {@code writerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 4} - */ - public abstract ByteBuf writeInt(int value); - - /** - * Sets the specified 64-bit long integer at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 8} - */ - public abstract ByteBuf writeLong(long value); - - /** - * Sets the specified 2-byte UTF-16 character at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} - * in this buffer. The 16 high-order bits of the specified value are ignored. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 2} - */ - public abstract ByteBuf writeChar(int value); - - /** - * Sets the specified 32-bit floating point number at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 4} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 4} - */ - public abstract ByteBuf writeFloat(float value); - - /** - * Sets the specified 64-bit floating point number at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 8} - */ - public abstract ByteBuf writeDouble(double value); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} until the source buffer becomes - * unreadable, and increases the {@code writerIndex} by the number of - * the transferred bytes. This method is basically same with - * {@link #writeBytes(ByteBuf, int, int)}, except that this method - * increases the {@code readerIndex} of the source buffer by the number of - * the transferred bytes while {@link #writeBytes(ByteBuf, int, int)} - * does not. - * - * @throws IndexOutOfBoundsException - * if {@code src.readableBytes} is greater than - * {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuf src); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code length}). This method - * is basically same with {@link #writeBytes(ByteBuf, int, int)}, - * except that this method increases the {@code readerIndex} of the source - * buffer by the number of the transferred bytes (= {@code length}) while - * {@link #writeBytes(ByteBuf, int, int)} does not. - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} or - * if {@code length} is greater then {@code src.readableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuf src, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param srcIndex the first index of the source - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code srcIndex + length} is greater than - * {@code src.capacity}, or - * if {@code length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length); - - /** - * Transfers the specified source array's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code src.length}). - * - * @throws IndexOutOfBoundsException - * if {@code src.length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(byte[] src); - - /** - * Transfers the specified source array's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param srcIndex the first index of the source - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code srcIndex + length} is greater than - * {@code src.length}, or - * if {@code length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} until the source buffer's position - * reaches its limit, and increases the {@code writerIndex} by the - * number of the transferred bytes. - * - * @throws IndexOutOfBoundsException - * if {@code src.remaining()} is greater than - * {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuffer src); - - /** - * Transfers the content of the specified stream to this buffer - * starting at the current {@code writerIndex} and increases the - * {@code writerIndex} by the number of the transferred bytes. - * - * @param length the number of bytes to transfer - * - * @return the actual number of bytes read in from the specified stream - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract int writeBytes(InputStream in, int length) throws IOException; - - /** - * Transfers the content of the specified channel to this buffer - * starting at the current {@code writerIndex} and increases the - * {@code writerIndex} by the number of the transferred bytes. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes read in from the specified channel - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException; - - /** - * Fills this buffer with NUL (0x00) starting at the current - * {@code writerIndex} and increases the {@code writerIndex} by the - * specified {@code length}. - * - * @param length the number of NULs to write to the buffer - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeZero(int length); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search takes place from the specified {@code fromIndex} - * (inclusive) to the specified {@code toIndex} (exclusive). - *

- * If {@code fromIndex} is greater than {@code toIndex}, the search is - * performed in a reversed order. - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the absolute index of the first occurrence if found. - * {@code -1} otherwise. - */ - public abstract int indexOf(int fromIndex, int toIndex, byte value); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search takes place from the current {@code readerIndex} - * (inclusive) to the current {@code writerIndex} (exclusive). - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the number of bytes between the current {@code readerIndex} - * and the first occurrence if found. {@code -1} otherwise. - */ - public abstract int bytesBefore(byte value); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search starts from the current {@code readerIndex} - * (inclusive) and lasts for the specified {@code length}. - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the number of bytes between the current {@code readerIndex} - * and the first occurrence if found. {@code -1} otherwise. - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract int bytesBefore(int length, byte value); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search starts from the specified {@code index} (inclusive) - * and lasts for the specified {@code length}. - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the number of bytes between the specified {@code index} - * and the first occurrence if found. {@code -1} otherwise. - * - * @throws IndexOutOfBoundsException - * if {@code index + length} is greater than {@code this.capacity} - */ - public abstract int bytesBefore(int index, int length, byte value); - - /** - * Iterates over the readable bytes of this buffer with the specified {@code processor} in ascending order. - * - * @return {@code -1} if the processor iterated to or beyond the end of the readable bytes. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByte(ByteBufProcessor processor); - - /** - * Iterates over the specified area of this buffer with the specified {@code processor} in ascending order. - * (i.e. {@code index}, {@code (index + 1)}, .. {@code (index + length - 1)}) - * - * @return {@code -1} if the processor iterated to or beyond the end of the specified area. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByte(int index, int length, ByteBufProcessor processor); - - /** - * Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order. - * - * @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByteDesc(ByteBufProcessor processor); - - /** - * Iterates over the specified area of this buffer with the specified {@code processor} in descending order. - * (i.e. {@code (index + length - 1)}, {@code (index + length - 2)}, ... {@code index}) - * - * - * @return {@code -1} if the processor iterated to or beyond the beginning of the specified area. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByteDesc(int index, int length, ByteBufProcessor processor); - - /** - * Returns a copy of this buffer's readable bytes. Modifying the content - * of the returned buffer or this buffer does not affect each other at all. - * This method is identical to {@code buf.copy(buf.readerIndex(), buf.readableBytes())}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - */ - public abstract ByteBuf copy(); - - /** - * Returns a copy of this buffer's sub-region. Modifying the content of - * the returned buffer or this buffer does not affect each other at all. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - */ - public abstract ByteBuf copy(int index, int length); - - /** - * Returns a slice of this buffer's readable bytes. Modifying the content - * of the returned buffer or this buffer affects each other's content - * while they maintain separate indexes and marks. This method is - * identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - */ - public abstract ByteBuf slice(); - - /** - * Returns a slice of this buffer's sub-region. Modifying the content of - * the returned buffer or this buffer affects each other's content while - * they maintain separate indexes and marks. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - */ - public abstract ByteBuf slice(int index, int length); - - /** - * Returns a buffer which shares the whole region of this buffer. - * Modifying the content of the returned buffer or this buffer affects - * each other's content while they maintain separate indexes and marks. - * This method is identical to {@code buf.slice(0, buf.capacity())}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - */ - public abstract ByteBuf duplicate(); - - /** - * Returns the maximum number of NIO {@link ByteBuffer}s that consist this buffer. Note that {@link #nioBuffers()} - * or {@link #nioBuffers(int, int)} might return a less number of {@link ByteBuffer}s. - * - * @return {@code -1} if this buffer has no underlying {@link ByteBuffer}. - * the number of the underlying {@link ByteBuffer}s if this buffer has at least one underlying - * {@link ByteBuffer}. Note that this method does not return {@code 0} to avoid confusion. - * - * @see #nioBuffer() - * @see #nioBuffer(int, int) - * @see #nioBuffers() - * @see #nioBuffers(int, int) - */ - public abstract int nioBufferCount(); - - /** - * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}. The returned buffer - * shares the content with this buffer, while changing the position and limit of the returned - * NIO buffer does not affect the indexes and marks of this buffer. This method is identical - * to {@code buf.nioBuffer(buf.readerIndex(), buf.readableBytes())}. This method does not - * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffers() - * @see #nioBuffers(int, int) - */ - public abstract ByteBuffer nioBuffer(); - - /** - * Exposes this buffer's sub-region as an NIO {@link ByteBuffer}. The returned buffer - * shares the content with this buffer, while changing the position and limit of the returned - * NIO buffer does not affect the indexes and marks of this buffer. This method does not - * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffers() - * @see #nioBuffers(int, int) - */ - public abstract ByteBuffer nioBuffer(int index, int length); - - /** - * Internal use only: Exposes the internal NIO buffer. - */ - public abstract ByteBuffer internalNioBuffer(int index, int length); - - /** - * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}'s. The returned buffer - * shares the content with this buffer, while changing the position and limit of the returned - * NIO buffer does not affect the indexes and marks of this buffer. This method does not - * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffer() - * @see #nioBuffer(int, int) - */ - public abstract ByteBuffer[] nioBuffers(); - - /** - * Exposes this buffer's bytes as an NIO {@link ByteBuffer}'s for the specified index and length - * The returned buffer shares the content with this buffer, while changing the position and limit - * of the returned NIO buffer does not affect the indexes and marks of this buffer. This method does - * not modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffer() - * @see #nioBuffer(int, int) - */ - public abstract ByteBuffer[] nioBuffers(int index, int length); - - /** - * Returns {@code true} if and only if this buffer has a backing byte array. - * If this method returns true, you can safely call {@link #array()} and - * {@link #arrayOffset()}. - */ - public abstract boolean hasArray(); - - /** - * Returns the backing byte array of this buffer. - * - * @throws UnsupportedOperationException - * if there no accessible backing byte array - */ - public abstract byte[] array(); - - /** - * Returns the offset of the first byte within the backing byte array of - * this buffer. - * - * @throws UnsupportedOperationException - * if there no accessible backing byte array - */ - public abstract int arrayOffset(); - - /** - * Returns {@code true} if and only if this buffer has a reference to the low-level memory address that points - * to the backing data. - */ - public abstract boolean hasMemoryAddress(); - - /** - * Returns the low-level memory address that point to the first byte of ths backing data. - * - * @throws UnsupportedOperationException - * if this buffer does not support accessing the low-level memory address - */ - public abstract long memoryAddress(); - - /** - * Decodes this buffer's readable bytes into a string with the specified - * character set name. This method is identical to - * {@code buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName)}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws UnsupportedCharsetException - * if the specified character set name is not supported by the - * current VM - */ - public abstract String toString(Charset charset); - - /** - * Decodes this buffer's sub-region into a string with the specified - * character set. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - */ - public abstract String toString(int index, int length, Charset charset); - - /** - * Returns a hash code which was calculated from the content of this - * buffer. If there's a byte array which is - * {@linkplain #equals(Object) equal to} this array, both arrays should - * return the same value. - */ - @Override - public abstract int hashCode(); - - /** - * Determines if the content of the specified buffer is identical to the - * content of this array. 'Identical' here means: - *

    - *
  • the size of the contents of the two buffers are same and
  • - *
  • every single byte of the content of the two buffers are same.
  • - *
- * Please note that it does not compare {@link #readerIndex()} nor - * {@link #writerIndex()}. This method also returns {@code false} for - * {@code null} and an object which is not an instance of - * {@link ByteBuf} type. - */ - @Override - public abstract boolean equals(Object obj); - - /** - * Compares the content of the specified buffer to the content of this - * buffer. Comparison is performed in the same manner with the string - * comparison functions of various languages such as {@code strcmp}, - * {@code memcmp} and {@link String#compareTo(String)}. - */ - @Override - public abstract int compareTo(ByteBuf buffer); - - /** - * Returns the string representation of this buffer. This method does not - * necessarily return the whole content of the buffer but returns - * the values of the key properties such as {@link #readerIndex()}, - * {@link #writerIndex()} and {@link #capacity()}. - */ - @Override - public abstract String toString(); - - @Override - public abstract ByteBuf retain(int increment); - - @Override - public abstract ByteBuf retain(); -} diff --git a/java/src/game/net/buffer/ByteBufAllocator.java b/java/src/game/net/buffer/ByteBufAllocator.java deleted file mode 100644 index f837722..0000000 --- a/java/src/game/net/buffer/ByteBufAllocator.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -/** - * Implementations are responsible to allocate buffers. Implementations of this interface are expected to be - * thread-safe. - */ -public interface ByteBufAllocator { - - ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR; - - /** - * Allocate a {@link ByteBuf}. If it is a direct or heap buffer - * depends on the actual implementation. - */ - ByteBuf buffer(); - - /** - * Allocate a {@link ByteBuf} with the given initial capacity. - * If it is a direct or heap buffer depends on the actual implementation. - */ - ByteBuf buffer(int initialCapacity); - - /** - * Allocate a {@link ByteBuf} with the given initial capacity and the given - * maximal capacity. If it is a direct or heap buffer depends on the actual - * implementation. - */ - ByteBuf buffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O. - */ - ByteBuf ioBuffer(); - - /** - * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O. - */ - ByteBuf ioBuffer(int initialCapacity); - - /** - * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O. - */ - ByteBuf ioBuffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a heap {@link ByteBuf}. - */ - ByteBuf heapBuffer(); - - /** - * Allocate a heap {@link ByteBuf} with the given initial capacity. - */ - ByteBuf heapBuffer(int initialCapacity); - - /** - * Allocate a heap {@link ByteBuf} with the given initial capacity and the given - * maximal capacity. - */ - ByteBuf heapBuffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a direct {@link ByteBuf}. - */ - ByteBuf directBuffer(); - - /** - * Allocate a direct {@link ByteBuf} with the given initial capacity. - */ - ByteBuf directBuffer(int initialCapacity); - - /** - * Allocate a direct {@link ByteBuf} with the given initial capacity and the given - * maximal capacity. - */ - ByteBuf directBuffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a {@link CompositeByteBuf}. - * If it is a direct or heap buffer depends on the actual implementation. - */ - CompositeByteBuf compositeBuffer(); - - /** - * Allocate a {@link CompositeByteBuf} with the given maximum number of components that can be stored in it. - * If it is a direct or heap buffer depends on the actual implementation. - */ - CompositeByteBuf compositeBuffer(int maxNumComponents); - - /** - * Allocate a heap {@link CompositeByteBuf}. - */ - CompositeByteBuf compositeHeapBuffer(); - - /** - * Allocate a heap {@link CompositeByteBuf} with the given maximum number of components that can be stored in it. - */ - CompositeByteBuf compositeHeapBuffer(int maxNumComponents); - - /** - * Allocate a direct {@link CompositeByteBuf}. - */ - CompositeByteBuf compositeDirectBuffer(); - - /** - * Allocate a direct {@link CompositeByteBuf} with the given maximum number of components that can be stored in it. - */ - CompositeByteBuf compositeDirectBuffer(int maxNumComponents); - - /** - * Returns {@code true} if direct {@link ByteBuf}'s are pooled - */ - boolean isDirectBufferPooled(); -} diff --git a/java/src/game/net/buffer/ByteBufInputStream.java b/java/src/game/net/buffer/ByteBufInputStream.java deleted file mode 100644 index 9affd26..0000000 --- a/java/src/game/net/buffer/ByteBufInputStream.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -/** - * An {@link InputStream} which reads data from a {@link ByteBuf}. - *

- * A read operation against this stream will occur at the {@code readerIndex} - * of its underlying buffer and the {@code readerIndex} will increase during - * the read operation. Please note that it only reads up to the number of - * readable bytes determined at the moment of construction. Therefore, - * updating {@link ByteBuf#writerIndex()} will not affect the return - * value of {@link #available()}. - *

- * This stream implements {@link DataInput} for your convenience. - * The endianness of the stream is not always big endian but depends on - * the endianness of the underlying buffer. - * - * @see ByteBufOutputStream - */ -public class ByteBufInputStream extends InputStream implements DataInput { - - private final ByteBuf buffer; - private final int startIndex; - private final int endIndex; - - /** - * Creates a new stream which reads data from the specified {@code buffer} - * starting at the current {@code readerIndex} and ending at the current - * {@code writerIndex}. - */ - public ByteBufInputStream(ByteBuf buffer) { - this(buffer, buffer.readableBytes()); - } - - /** - * Creates a new stream which reads data from the specified {@code buffer} - * starting at the current {@code readerIndex} and ending at - * {@code readerIndex + length}. - * - * @throws IndexOutOfBoundsException - * if {@code readerIndex + length} is greater than - * {@code writerIndex} - */ - public ByteBufInputStream(ByteBuf buffer, int length) { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - if (length < 0) { - throw new IllegalArgumentException("length: " + length); - } - if (length > buffer.readableBytes()) { - throw new IndexOutOfBoundsException("Too many bytes to be read - Needs " - + length + ", maximum is " + buffer.readableBytes()); - } - - this.buffer = buffer; - startIndex = buffer.readerIndex(); - endIndex = startIndex + length; - buffer.markReaderIndex(); - } - - /** - * Returns the number of read bytes by this stream so far. - */ - public int readBytes() { - return buffer.readerIndex() - startIndex; - } - - @Override - public int available() throws IOException { - return endIndex - buffer.readerIndex(); - } - - @Override - public void mark(int readlimit) { - buffer.markReaderIndex(); - } - - @Override - public boolean markSupported() { - return true; - } - - @Override - public int read() throws IOException { - if (!buffer.isReadable()) { - return -1; - } - return buffer.readByte() & 0xff; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - int available = available(); - if (available == 0) { - return -1; - } - - len = Math.min(available, len); - buffer.readBytes(b, off, len); - return len; - } - - @Override - public void reset() throws IOException { - buffer.resetReaderIndex(); - } - - @Override - public long skip(long n) throws IOException { - if (n > Integer.MAX_VALUE) { - return skipBytes(Integer.MAX_VALUE); - } else { - return skipBytes((int) n); - } - } - - @Override - public boolean readBoolean() throws IOException { - checkAvailable(1); - return read() != 0; - } - - @Override - public byte readByte() throws IOException { - if (!buffer.isReadable()) { - throw new EOFException(); - } - return buffer.readByte(); - } - - @Override - public char readChar() throws IOException { - return (char) readShort(); - } - - @Override - public double readDouble() throws IOException { - return Double.longBitsToDouble(readLong()); - } - - @Override - public float readFloat() throws IOException { - return Float.intBitsToFloat(readInt()); - } - - @Override - public void readFully(byte[] b) throws IOException { - readFully(b, 0, b.length); - } - - @Override - public void readFully(byte[] b, int off, int len) throws IOException { - checkAvailable(len); - buffer.readBytes(b, off, len); - } - - @Override - public int readInt() throws IOException { - checkAvailable(4); - return buffer.readInt(); - } - - private final StringBuilder lineBuf = new StringBuilder(); - - @Override - public String readLine() throws IOException { - lineBuf.setLength(0); - - loop: while (true) { - if (!buffer.isReadable()) { - return lineBuf.length() > 0 ? lineBuf.toString() : null; - } - - int c = buffer.readUnsignedByte(); - switch (c) { - case '\n': - break loop; - - case '\r': - if (buffer.isReadable() && (char) buffer.getUnsignedByte(buffer.readerIndex()) == '\n') { - buffer.skipBytes(1); - } - break loop; - - default: - lineBuf.append((char) c); - } - } - - return lineBuf.toString(); - } - - @Override - public long readLong() throws IOException { - checkAvailable(8); - return buffer.readLong(); - } - - @Override - public short readShort() throws IOException { - checkAvailable(2); - return buffer.readShort(); - } - - @Override - public String readUTF() throws IOException { - return DataInputStream.readUTF(this); - } - - @Override - public int readUnsignedByte() throws IOException { - return readByte() & 0xff; - } - - @Override - public int readUnsignedShort() throws IOException { - return readShort() & 0xffff; - } - - @Override - public int skipBytes(int n) throws IOException { - int nBytes = Math.min(available(), n); - buffer.skipBytes(nBytes); - return nBytes; - } - - private void checkAvailable(int fieldSize) throws IOException { - if (fieldSize < 0) { - throw new IndexOutOfBoundsException("fieldSize cannot be a negative number"); - } - if (fieldSize > available()) { - throw new EOFException("fieldSize is too long! Length is " + fieldSize - + ", but maximum is " + available()); - } - } -} diff --git a/java/src/game/net/buffer/ByteBufOutputStream.java b/java/src/game/net/buffer/ByteBufOutputStream.java deleted file mode 100644 index dd79c0f..0000000 --- a/java/src/game/net/buffer/ByteBufOutputStream.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * An {@link OutputStream} which writes data to a {@link ByteBuf}. - *

- * A write operation against this stream will occur at the {@code writerIndex} - * of its underlying buffer and the {@code writerIndex} will increase during - * the write operation. - *

- * This stream implements {@link DataOutput} for your convenience. - * The endianness of the stream is not always big endian but depends on - * the endianness of the underlying buffer. - * - * @see ByteBufInputStream - */ -public class ByteBufOutputStream extends OutputStream implements DataOutput { - - private final ByteBuf buffer; - private final int startIndex; - private final DataOutputStream utf8out = new DataOutputStream(this); - - /** - * Creates a new stream which writes data to the specified {@code buffer}. - */ - public ByteBufOutputStream(ByteBuf buffer) { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - this.buffer = buffer; - startIndex = buffer.writerIndex(); - } - - /** - * Returns the number of written bytes by this stream so far. - */ - public int writtenBytes() { - return buffer.writerIndex() - startIndex; - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - if (len == 0) { - return; - } - - buffer.writeBytes(b, off, len); - } - - @Override - public void write(byte[] b) throws IOException { - buffer.writeBytes(b); - } - - @Override - public void write(int b) throws IOException { - buffer.writeByte((byte) b); - } - - @Override - public void writeBoolean(boolean v) throws IOException { - write(v? (byte) 1 : (byte) 0); - } - - @Override - public void writeByte(int v) throws IOException { - write(v); - } - - @Override - public void writeBytes(String s) throws IOException { - int len = s.length(); - for (int i = 0; i < len; i ++) { - write((byte) s.charAt(i)); - } - } - - @Override - public void writeChar(int v) throws IOException { - writeShort((short) v); - } - - @Override - public void writeChars(String s) throws IOException { - int len = s.length(); - for (int i = 0 ; i < len ; i ++) { - writeChar(s.charAt(i)); - } - } - - @Override - public void writeDouble(double v) throws IOException { - writeLong(Double.doubleToLongBits(v)); - } - - @Override - public void writeFloat(float v) throws IOException { - writeInt(Float.floatToIntBits(v)); - } - - @Override - public void writeInt(int v) throws IOException { - buffer.writeInt(v); - } - - @Override - public void writeLong(long v) throws IOException { - buffer.writeLong(v); - } - - @Override - public void writeShort(int v) throws IOException { - buffer.writeShort((short) v); - } - - @Override - public void writeUTF(String s) throws IOException { - utf8out.writeUTF(s); - } - - /** - * Returns the buffer where this stream is writing data. - */ - public ByteBuf buffer() { - return buffer; - } -} diff --git a/java/src/game/net/buffer/ByteBufProcessor.java b/java/src/game/net/buffer/ByteBufProcessor.java deleted file mode 100644 index d75db82..0000000 --- a/java/src/game/net/buffer/ByteBufProcessor.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -public interface ByteBufProcessor { - - /** - * Aborts on a {@code NUL (0x00)}. - */ - ByteBufProcessor FIND_NUL = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != 0; - } - }; - - /** - * Aborts on a non-{@code NUL (0x00)}. - */ - ByteBufProcessor FIND_NON_NUL = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == 0; - } - }; - - /** - * Aborts on a {@code CR ('\r')}. - */ - ByteBufProcessor FIND_CR = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != '\r'; - } - }; - - /** - * Aborts on a non-{@code CR ('\r')}. - */ - ByteBufProcessor FIND_NON_CR = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == '\r'; - } - }; - - /** - * Aborts on a {@code LF ('\n')}. - */ - ByteBufProcessor FIND_LF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != '\n'; - } - }; - - /** - * Aborts on a non-{@code LF ('\n')}. - */ - ByteBufProcessor FIND_NON_LF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == '\n'; - } - }; - - /** - * Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}. - */ - ByteBufProcessor FIND_CRLF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != '\r' && value != '\n'; - } - }; - - /** - * Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}. - */ - ByteBufProcessor FIND_NON_CRLF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == '\r' || value == '\n'; - } - }; - - /** - * Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}). - */ - ByteBufProcessor FIND_LINEAR_WHITESPACE = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != ' ' && value != '\t'; - } - }; - - /** - * Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}). - */ - ByteBufProcessor FIND_NON_LINEAR_WHITESPACE = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == ' ' || value == '\t'; - } - }; - - /** - * @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer. - * {@code false} if the processor wants to stop handling bytes and abort the loop. - */ - boolean process(byte value) throws Exception; -} diff --git a/java/src/game/net/buffer/ByteBufUtil.java b/java/src/game/net/buffer/ByteBufUtil.java deleted file mode 100644 index 365236d..0000000 --- a/java/src/game/net/buffer/ByteBufUtil.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.util.Locale; - -import game.net.util.CharsetUtil; -import game.net.util.Recycler; -import game.net.util.Recycler.Handle; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.SystemPropertyUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A collection of utility methods that is related with handling {@link ByteBuf}. - */ -public final class ByteBufUtil { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ByteBufUtil.class); - - private static final char[] HEXDUMP_TABLE = new char[256 * 4]; - - static final ByteBufAllocator DEFAULT_ALLOCATOR; - - private static final int THREAD_LOCAL_BUFFER_SIZE; - - static { - final char[] DIGITS = "0123456789abcdef".toCharArray(); - for (int i = 0; i < 256; i ++) { - HEXDUMP_TABLE[ i << 1 ] = DIGITS[i >>> 4 & 0x0F]; - HEXDUMP_TABLE[(i << 1) + 1] = DIGITS[i & 0x0F]; - } - - String allocType = SystemPropertyUtil.get("io.netty.allocator.type", "unpooled").toLowerCase(Locale.US).trim(); - ByteBufAllocator alloc; - if ("unpooled".equals(allocType)) { - alloc = UnpooledByteBufAllocator.DEFAULT; - logger.debug("-Dio.netty.allocator.type: {}", allocType); - } else if ("pooled".equals(allocType)) { - alloc = PooledByteBufAllocator.DEFAULT; - logger.debug("-Dio.netty.allocator.type: {}", allocType); - } else { - alloc = UnpooledByteBufAllocator.DEFAULT; - logger.debug("-Dio.netty.allocator.type: unpooled (unknown: {})", allocType); - } - - DEFAULT_ALLOCATOR = alloc; - - THREAD_LOCAL_BUFFER_SIZE = SystemPropertyUtil.getInt("io.netty.threadLocalDirectBufferSize", 64 * 1024); - logger.debug("-Dio.netty.threadLocalDirectBufferSize: {}", THREAD_LOCAL_BUFFER_SIZE); - } - - /** - * Returns a hex dump - * of the specified buffer's readable bytes. - */ - public static String hexDump(ByteBuf buffer) { - return hexDump(buffer, buffer.readerIndex(), buffer.readableBytes()); - } - - /** - * Returns a hex dump - * of the specified buffer's sub-region. - */ - public static String hexDump(ByteBuf buffer, int fromIndex, int length) { - if (length < 0) { - throw new IllegalArgumentException("length: " + length); - } - if (length == 0) { - return ""; - } - - int endIndex = fromIndex + length; - char[] buf = new char[length << 1]; - - int srcIdx = fromIndex; - int dstIdx = 0; - for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) { - System.arraycopy( - HEXDUMP_TABLE, buffer.getUnsignedByte(srcIdx) << 1, - buf, dstIdx, 2); - } - - return new String(buf); - } - - /** - * Calculates the hash code of the specified buffer. This method is - * useful when implementing a new buffer type. - */ - public static int hashCode(ByteBuf buffer) { - final int aLen = buffer.readableBytes(); - final int intCount = aLen >>> 2; - final int byteCount = aLen & 3; - - int hashCode = 1; - int arrayIndex = buffer.readerIndex(); - if (buffer.order() == ByteOrder.BIG_ENDIAN) { - for (int i = intCount; i > 0; i --) { - hashCode = 31 * hashCode + buffer.getInt(arrayIndex); - arrayIndex += 4; - } - } else { - for (int i = intCount; i > 0; i --) { - hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex)); - arrayIndex += 4; - } - } - - for (int i = byteCount; i > 0; i --) { - hashCode = 31 * hashCode + buffer.getByte(arrayIndex ++); - } - - if (hashCode == 0) { - hashCode = 1; - } - - return hashCode; - } - - /** - * Returns {@code true} if and only if the two specified buffers are - * identical to each other as described in {@code ChannelBuffer#equals(Object)}. - * This method is useful when implementing a new buffer type. - */ - public static boolean equals(ByteBuf bufferA, ByteBuf bufferB) { - final int aLen = bufferA.readableBytes(); - if (aLen != bufferB.readableBytes()) { - return false; - } - - final int longCount = aLen >>> 3; - final int byteCount = aLen & 7; - - int aIndex = bufferA.readerIndex(); - int bIndex = bufferB.readerIndex(); - - if (bufferA.order() == bufferB.order()) { - for (int i = longCount; i > 0; i --) { - if (bufferA.getLong(aIndex) != bufferB.getLong(bIndex)) { - return false; - } - aIndex += 8; - bIndex += 8; - } - } else { - for (int i = longCount; i > 0; i --) { - if (bufferA.getLong(aIndex) != swapLong(bufferB.getLong(bIndex))) { - return false; - } - aIndex += 8; - bIndex += 8; - } - } - - for (int i = byteCount; i > 0; i --) { - if (bufferA.getByte(aIndex) != bufferB.getByte(bIndex)) { - return false; - } - aIndex ++; - bIndex ++; - } - - return true; - } - - /** - * Compares the two specified buffers as described in {@link ByteBuf#compareTo(ByteBuf)}. - * This method is useful when implementing a new buffer type. - */ - public static int compare(ByteBuf bufferA, ByteBuf bufferB) { - final int aLen = bufferA.readableBytes(); - final int bLen = bufferB.readableBytes(); - final int minLength = Math.min(aLen, bLen); - final int uintCount = minLength >>> 2; - final int byteCount = minLength & 3; - - int aIndex = bufferA.readerIndex(); - int bIndex = bufferB.readerIndex(); - - if (bufferA.order() == bufferB.order()) { - for (int i = uintCount; i > 0; i --) { - long va = bufferA.getUnsignedInt(aIndex); - long vb = bufferB.getUnsignedInt(bIndex); - if (va > vb) { - return 1; - } - if (va < vb) { - return -1; - } - aIndex += 4; - bIndex += 4; - } - } else { - for (int i = uintCount; i > 0; i --) { - long va = bufferA.getUnsignedInt(aIndex); - long vb = swapInt(bufferB.getInt(bIndex)) & 0xFFFFFFFFL; - if (va > vb) { - return 1; - } - if (va < vb) { - return -1; - } - aIndex += 4; - bIndex += 4; - } - } - - for (int i = byteCount; i > 0; i --) { - short va = bufferA.getUnsignedByte(aIndex); - short vb = bufferB.getUnsignedByte(bIndex); - if (va > vb) { - return 1; - } - if (va < vb) { - return -1; - } - aIndex ++; - bIndex ++; - } - - return aLen - bLen; - } - - /** - * The default implementation of {@link ByteBuf#indexOf(int, int, byte)}. - * This method is useful when implementing a new buffer type. - */ - public static int indexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) { - if (fromIndex <= toIndex) { - return firstIndexOf(buffer, fromIndex, toIndex, value); - } else { - return lastIndexOf(buffer, fromIndex, toIndex, value); - } - } - - /** - * Toggles the endianness of the specified 16-bit short integer. - */ - public static short swapShort(short value) { - return Short.reverseBytes(value); - } - - /** - * Toggles the endianness of the specified 24-bit medium integer. - */ - public static int swapMedium(int value) { - int swapped = value << 16 & 0xff0000 | value & 0xff00 | value >>> 16 & 0xff; - if ((swapped & 0x800000) != 0) { - swapped |= 0xff000000; - } - return swapped; - } - - /** - * Toggles the endianness of the specified 32-bit integer. - */ - public static int swapInt(int value) { - return Integer.reverseBytes(value); - } - - /** - * Toggles the endianness of the specified 64-bit long integer. - */ - public static long swapLong(long value) { - return Long.reverseBytes(value); - } - - /** - * Read the given amount of bytes into a new {@link ByteBuf} that is allocated from the {@link ByteBufAllocator}. - */ - public static ByteBuf readBytes(ByteBufAllocator alloc, ByteBuf buffer, int length) { - boolean release = true; - ByteBuf dst = alloc.buffer(length); - try { - buffer.readBytes(dst); - release = false; - return dst; - } finally { - if (release) { - dst.release(); - } - } - } - - private static int firstIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) { - fromIndex = Math.max(fromIndex, 0); - if (fromIndex >= toIndex || buffer.capacity() == 0) { - return -1; - } - - for (int i = fromIndex; i < toIndex; i ++) { - if (buffer.getByte(i) == value) { - return i; - } - } - - return -1; - } - - private static int lastIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) { - fromIndex = Math.min(fromIndex, buffer.capacity()); - if (fromIndex < 0 || buffer.capacity() == 0) { - return -1; - } - - for (int i = fromIndex - 1; i >= toIndex; i --) { - if (buffer.getByte(i) == value) { - return i; - } - } - - return -1; - } - - /** - * Encode the given {@link CharBuffer} using the given {@link Charset} into a new {@link ByteBuf} which - * is allocated via the {@link ByteBufAllocator}. - */ - public static ByteBuf encodeString(ByteBufAllocator alloc, CharBuffer src, Charset charset) { - return encodeString0(alloc, false, src, charset); - } - - static ByteBuf encodeString0(ByteBufAllocator alloc, boolean enforceHeap, CharBuffer src, Charset charset) { - final CharsetEncoder encoder = CharsetUtil.getEncoder(charset); - int length = (int) ((double) src.remaining() * encoder.maxBytesPerChar()); - boolean release = true; - final ByteBuf dst; - if (enforceHeap) { - dst = alloc.heapBuffer(length); - } else { - dst = alloc.buffer(length); - } - try { - final ByteBuffer dstBuf = dst.internalNioBuffer(0, length); - final int pos = dstBuf.position(); - CoderResult cr = encoder.encode(src, dstBuf, true); - if (!cr.isUnderflow()) { - cr.throwException(); - } - cr = encoder.flush(dstBuf); - if (!cr.isUnderflow()) { - cr.throwException(); - } - dst.writerIndex(dst.writerIndex() + dstBuf.position() - pos); - release = false; - return dst; - } catch (CharacterCodingException x) { - throw new IllegalStateException(x); - } finally { - if (release) { - dst.release(); - } - } - } - - static String decodeString(ByteBuffer src, Charset charset) { - final CharsetDecoder decoder = CharsetUtil.getDecoder(charset); - final CharBuffer dst = CharBuffer.allocate( - (int) ((double) src.remaining() * decoder.maxCharsPerByte())); - try { - CoderResult cr = decoder.decode(src, dst, true); - if (!cr.isUnderflow()) { - cr.throwException(); - } - cr = decoder.flush(dst); - if (!cr.isUnderflow()) { - cr.throwException(); - } - } catch (CharacterCodingException x) { - throw new IllegalStateException(x); - } - return dst.flip().toString(); - } - - /** - * Returns a cached thread-local direct buffer, if available. - * - * @return a cached thread-local direct buffer, if available. {@code null} otherwise. - */ - public static ByteBuf threadLocalDirectBuffer() { - if (THREAD_LOCAL_BUFFER_SIZE <= 0) { - return null; - } - - if (PlatformDependent.hasUnsafe()) { - return ThreadLocalUnsafeDirectByteBuf.newInstance(); - } else { - return ThreadLocalDirectByteBuf.newInstance(); - } - } - - static final class ThreadLocalUnsafeDirectByteBuf extends UnpooledUnsafeDirectByteBuf { - - private static final Recycler RECYCLER = - new Recycler() { - @Override - protected ThreadLocalUnsafeDirectByteBuf newObject(Handle handle) { - return new ThreadLocalUnsafeDirectByteBuf(handle); - } - }; - - static ThreadLocalUnsafeDirectByteBuf newInstance() { - ThreadLocalUnsafeDirectByteBuf buf = RECYCLER.get(); - buf.setRefCnt(1); - return buf; - } - - private final Handle handle; - - private ThreadLocalUnsafeDirectByteBuf(Handle handle) { - super(UnpooledByteBufAllocator.DEFAULT, 256, Integer.MAX_VALUE); - this.handle = handle; - } - - @Override - protected void deallocate() { - if (capacity() > THREAD_LOCAL_BUFFER_SIZE) { - super.deallocate(); - } else { - clear(); - RECYCLER.recycle(this, handle); - } - } - } - - static final class ThreadLocalDirectByteBuf extends UnpooledDirectByteBuf { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected ThreadLocalDirectByteBuf newObject(Handle handle) { - return new ThreadLocalDirectByteBuf(handle); - } - }; - - static ThreadLocalDirectByteBuf newInstance() { - ThreadLocalDirectByteBuf buf = RECYCLER.get(); - buf.setRefCnt(1); - return buf; - } - - private final Handle handle; - - private ThreadLocalDirectByteBuf(Handle handle) { - super(UnpooledByteBufAllocator.DEFAULT, 256, Integer.MAX_VALUE); - this.handle = handle; - } - - @Override - protected void deallocate() { - if (capacity() > THREAD_LOCAL_BUFFER_SIZE) { - super.deallocate(); - } else { - clear(); - RECYCLER.recycle(this, handle); - } - } - } - - private ByteBufUtil() { } -} diff --git a/java/src/game/net/buffer/CompositeByteBuf.java b/java/src/game/net/buffer/CompositeByteBuf.java deleted file mode 100644 index ff0994b..0000000 --- a/java/src/game/net/buffer/CompositeByteBuf.java +++ /dev/null @@ -1,1602 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import game.net.util.ResourceLeak; -import game.net.util.internal.EmptyArrays; - -/** - * A virtual buffer which shows multiple buffers as a single merged buffer. It is recommended to use - * {@link ByteBufAllocator#compositeBuffer()} or {@link Unpooled#wrappedBuffer(ByteBuf...)} instead of calling the - * constructor explicitly. - */ -public class CompositeByteBuf extends AbstractReferenceCountedByteBuf { - - private final ResourceLeak leak; - private final ByteBufAllocator alloc; - private final boolean direct; - private final List components = new ArrayList(); - private final int maxNumComponents; - private static final ByteBuffer FULL_BYTEBUFFER = (ByteBuffer) ByteBuffer.allocate(1).position(1); - - private boolean freed; - - public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - leak = leakDetector.open(this); - } - - public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (maxNumComponents < 2) { - throw new IllegalArgumentException( - "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); - } - - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - - addComponents0(0, buffers); - consolidateIfNeeded(); - setIndex(0, capacity()); - leak = leakDetector.open(this); - } - - public CompositeByteBuf( - ByteBufAllocator alloc, boolean direct, int maxNumComponents, Iterable buffers) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (maxNumComponents < 2) { - throw new IllegalArgumentException( - "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); - } - - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - addComponents0(0, buffers); - consolidateIfNeeded(); - setIndex(0, capacity()); - leak = leakDetector.open(this); - } - - /** - * Add the given {@link ByteBuf}. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffer the {@link ByteBuf} to add - */ - public CompositeByteBuf addComponent(ByteBuf buffer) { - addComponent0(components.size(), buffer); - consolidateIfNeeded(); - return this; - } - - /** - * Add the given {@link ByteBuf}s. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(ByteBuf... buffers) { - addComponents0(components.size(), buffers); - consolidateIfNeeded(); - return this; - } - - /** - * Add the given {@link ByteBuf}s. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(Iterable buffers) { - addComponents0(components.size(), buffers); - consolidateIfNeeded(); - return this; - } - - /** - * Add the given {@link ByteBuf} on the specific index. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param cIndex the index on which the {@link ByteBuf} will be added - * @param buffer the {@link ByteBuf} to add - */ - public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) { - addComponent0(cIndex, buffer); - consolidateIfNeeded(); - return this; - } - - private int addComponent0(int cIndex, ByteBuf buffer) { - checkComponentIndex(cIndex); - - if (buffer == null) { - throw new NullPointerException("buffer"); - } - - int readableBytes = buffer.readableBytes(); - if (readableBytes == 0) { - return cIndex; - } - - // No need to consolidate - just add a component to the list. - Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice()); - if (cIndex == components.size()) { - components.add(c); - if (cIndex == 0) { - c.endOffset = readableBytes; - } else { - Component prev = components.get(cIndex - 1); - c.offset = prev.endOffset; - c.endOffset = c.offset + readableBytes; - } - } else { - components.add(cIndex, c); - updateComponentOffsets(cIndex); - } - return cIndex; - } - - /** - * Add the given {@link ByteBuf}s on the specific index - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param cIndex the index on which the {@link ByteBuf} will be added. - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) { - addComponents0(cIndex, buffers); - consolidateIfNeeded(); - return this; - } - - private int addComponents0(int cIndex, ByteBuf... buffers) { - checkComponentIndex(cIndex); - - if (buffers == null) { - throw new NullPointerException("buffers"); - } - - int readableBytes = 0; - for (ByteBuf b: buffers) { - if (b == null) { - break; - } - readableBytes += b.readableBytes(); - } - - if (readableBytes == 0) { - return cIndex; - } - - // No need for consolidation - for (ByteBuf b: buffers) { - if (b == null) { - break; - } - if (b.isReadable()) { - cIndex = addComponent0(cIndex, b) + 1; - int size = components.size(); - if (cIndex > size) { - cIndex = size; - } - } else { - b.release(); - } - } - return cIndex; - } - - /** - * Add the given {@link ByteBuf}s on the specific index - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param cIndex the index on which the {@link ByteBuf} will be added. - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(int cIndex, Iterable buffers) { - addComponents0(cIndex, buffers); - consolidateIfNeeded(); - return this; - } - - private int addComponents0(int cIndex, Iterable buffers) { - if (buffers == null) { - throw new NullPointerException("buffers"); - } - - if (buffers instanceof ByteBuf) { - // If buffers also implements ByteBuf (e.g. CompositeByteBuf), it has to go to addComponent(ByteBuf). - return addComponent0(cIndex, (ByteBuf) buffers); - } - - if (!(buffers instanceof Collection)) { - List list = new ArrayList(); - for (ByteBuf b: buffers) { - list.add(b); - } - buffers = list; - } - - Collection col = (Collection) buffers; - return addComponents0(cIndex, col.toArray(new ByteBuf[col.size()])); - } - - /** - * This should only be called as last operation from a method as this may adjust the underlying - * array of components and so affect the index etc. - */ - private void consolidateIfNeeded() { - // Consolidate if the number of components will exceed the allowed maximum by the current - // operation. - final int numComponents = components.size(); - if (numComponents > maxNumComponents) { - final int capacity = components.get(numComponents - 1).endOffset; - - ByteBuf consolidated = allocBuffer(capacity); - - // We're not using foreach to avoid creating an iterator. - for (int i = 0; i < numComponents; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - Component c = new Component(consolidated); - c.endOffset = c.length; - components.clear(); - components.add(c); - } - } - - private void checkComponentIndex(int cIndex) { - ensureAccessible(); - if (cIndex < 0 || cIndex > components.size()) { - throw new IndexOutOfBoundsException(String.format( - "cIndex: %d (expected: >= 0 && <= numComponents(%d))", - cIndex, components.size())); - } - } - - private void checkComponentIndex(int cIndex, int numComponents) { - ensureAccessible(); - if (cIndex < 0 || cIndex + numComponents > components.size()) { - throw new IndexOutOfBoundsException(String.format( - "cIndex: %d, numComponents: %d " + - "(expected: cIndex >= 0 && cIndex + numComponents <= totalNumComponents(%d))", - cIndex, numComponents, components.size())); - } - } - - private void updateComponentOffsets(int cIndex) { - int size = components.size(); - if (size <= cIndex) { - return; - } - - Component c = components.get(cIndex); - if (cIndex == 0) { - c.offset = 0; - c.endOffset = c.length; - cIndex ++; - } - - for (int i = cIndex; i < size; i ++) { - Component prev = components.get(i - 1); - Component cur = components.get(i); - cur.offset = prev.endOffset; - cur.endOffset = cur.offset + cur.length; - } - } - - /** - * Remove the {@link ByteBuf} from the given index. - * - * @param cIndex the index on from which the {@link ByteBuf} will be remove - */ - public CompositeByteBuf removeComponent(int cIndex) { - checkComponentIndex(cIndex); - components.remove(cIndex).freeIfNecessary(); - updateComponentOffsets(cIndex); - return this; - } - - /** - * Remove the number of {@link ByteBuf}s starting from the given index. - * - * @param cIndex the index on which the {@link ByteBuf}s will be started to removed - * @param numComponents the number of components to remove - */ - public CompositeByteBuf removeComponents(int cIndex, int numComponents) { - checkComponentIndex(cIndex, numComponents); - - List toRemove = components.subList(cIndex, cIndex + numComponents); - for (Component c: toRemove) { - c.freeIfNecessary(); - } - toRemove.clear(); - - updateComponentOffsets(cIndex); - return this; - } - - public Iterator iterator() { - ensureAccessible(); - List list = new ArrayList(components.size()); - for (Component c: components) { - list.add(c.buf); - } - return list.iterator(); - } - - /** - * Same with {@link #slice(int, int)} except that this method returns a list. - */ - public List decompose(int offset, int length) { - checkIndex(offset, length); - if (length == 0) { - return Collections.emptyList(); - } - - int componentId = toComponentIndex(offset); - List slice = new ArrayList(components.size()); - - // The first component - Component firstC = components.get(componentId); - ByteBuf first = firstC.buf.duplicate(); - first.readerIndex(offset - firstC.offset); - - ByteBuf buf = first; - int bytesToSlice = length; - do { - int readableBytes = buf.readableBytes(); - if (bytesToSlice <= readableBytes) { - // Last component - buf.writerIndex(buf.readerIndex() + bytesToSlice); - slice.add(buf); - break; - } else { - // Not the last component - slice.add(buf); - bytesToSlice -= readableBytes; - componentId ++; - - // Fetch the next component. - buf = components.get(componentId).buf.duplicate(); - } - } while (bytesToSlice > 0); - - // Slice all components because only readable bytes are interesting. - for (int i = 0; i < slice.size(); i ++) { - slice.set(i, slice.get(i).slice()); - } - - return slice; - } - - @Override - public boolean isDirect() { - int size = components.size(); - if (size == 0) { - return false; - } - for (int i = 0; i < size; i++) { - if (!components.get(i).buf.isDirect()) { - return false; - } - } - return true; - } - - @Override - public boolean hasArray() { - if (components.size() == 1) { - return components.get(0).buf.hasArray(); - } - return false; - } - - @Override - public byte[] array() { - if (components.size() == 1) { - return components.get(0).buf.array(); - } - throw new UnsupportedOperationException(); - } - - @Override - public int arrayOffset() { - if (components.size() == 1) { - return components.get(0).buf.arrayOffset(); - } - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasMemoryAddress() { - if (components.size() == 1) { - return components.get(0).buf.hasMemoryAddress(); - } - return false; - } - - @Override - public long memoryAddress() { - if (components.size() == 1) { - return components.get(0).buf.memoryAddress(); - } - throw new UnsupportedOperationException(); - } - - @Override - public int capacity() { - if (components.isEmpty()) { - return 0; - } - return components.get(components.size() - 1).endOffset; - } - - @Override - public CompositeByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int oldCapacity = capacity(); - if (newCapacity > oldCapacity) { - final int paddingLength = newCapacity - oldCapacity; - ByteBuf padding; - int nComponents = components.size(); - if (nComponents < maxNumComponents) { - padding = allocBuffer(paddingLength); - padding.setIndex(0, paddingLength); - addComponent0(components.size(), padding); - } else { - padding = allocBuffer(paddingLength); - padding.setIndex(0, paddingLength); - // FIXME: No need to create a padding buffer and consolidate. - // Just create a big single buffer and put the current content there. - addComponent0(components.size(), padding); - consolidateIfNeeded(); - } - } else if (newCapacity < oldCapacity) { - int bytesToTrim = oldCapacity - newCapacity; - for (ListIterator i = components.listIterator(components.size()); i.hasPrevious();) { - Component c = i.previous(); - if (bytesToTrim >= c.length) { - bytesToTrim -= c.length; - i.remove(); - continue; - } - - // Replace the last component with the trimmed slice. - Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim)); - newC.offset = c.offset; - newC.endOffset = newC.offset + newC.length; - i.set(newC); - break; - } - - if (readerIndex() > newCapacity) { - setIndex(newCapacity, newCapacity); - } else if (writerIndex() > newCapacity) { - writerIndex(newCapacity); - } - } - return this; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - /** - * Return the current number of {@link ByteBuf}'s that are composed in this instance - */ - public int numComponents() { - return components.size(); - } - - /** - * Return the max number of {@link ByteBuf}'s that are composed in this instance - */ - public int maxNumComponents() { - return maxNumComponents; - } - - /** - * Return the index for the given offset - */ - public int toComponentIndex(int offset) { - checkIndex(offset); - - for (int low = 0, high = components.size(); low <= high;) { - int mid = low + high >>> 1; - Component c = components.get(mid); - if (offset >= c.endOffset) { - low = mid + 1; - } else if (offset < c.offset) { - high = mid - 1; - } else { - return mid; - } - } - - throw new Error("should not reach here"); - } - - public int toByteIndex(int cIndex) { - checkComponentIndex(cIndex); - return components.get(cIndex).offset; - } - - @Override - public byte getByte(int index) { - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - Component c = findComponent(index); - return c.buf.getByte(index - c.offset); - } - - @Override - protected short _getShort(int index) { - Component c = findComponent(index); - if (index + 2 <= c.endOffset) { - return c.buf.getShort(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff); - } else { - return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8); - } - } - - @Override - protected int _getUnsignedMedium(int index) { - Component c = findComponent(index); - if (index + 3 <= c.endOffset) { - return c.buf.getUnsignedMedium(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff; - } else { - return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16; - } - } - - @Override - protected int _getInt(int index) { - Component c = findComponent(index); - if (index + 4 <= c.endOffset) { - return c.buf.getInt(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff; - } else { - return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16; - } - } - - @Override - protected long _getLong(int index) { - Component c = findComponent(index); - if (index + 8 <= c.endOffset) { - return c.buf.getLong(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL; - } else { - return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32; - } - } - - @Override - public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuffer dst) { - int limit = dst.limit(); - int length = dst.remaining(); - - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - try { - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - dst.limit(dst.position() + localLength); - s.getBytes(index - adjustment, dst); - index += localLength; - length -= localLength; - i ++; - } - } finally { - dst.limit(limit); - } - return this; - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - int count = nioBufferCount(); - if (count == 1) { - return out.write(internalNioBuffer(index, length)); - } else { - long writtenBytes = out.write(nioBuffers(index, length)); - if (writtenBytes > Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } else { - return (int) writtenBytes; - } - } - } - - @Override - public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, out, localLength); - index += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf setByte(int index, int value) { - Component c = findComponent(index); - c.buf.setByte(index - c.offset, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - setByte(index, value); - } - - @Override - public CompositeByteBuf setShort(int index, int value) { - return (CompositeByteBuf) super.setShort(index, value); - } - - @Override - protected void _setShort(int index, int value) { - Component c = findComponent(index); - if (index + 2 <= c.endOffset) { - c.buf.setShort(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setByte(index, (byte) (value >>> 8)); - _setByte(index + 1, (byte) value); - } else { - _setByte(index, (byte) value); - _setByte(index + 1, (byte) (value >>> 8)); - } - } - - @Override - public CompositeByteBuf setMedium(int index, int value) { - return (CompositeByteBuf) super.setMedium(index, value); - } - - @Override - protected void _setMedium(int index, int value) { - Component c = findComponent(index); - if (index + 3 <= c.endOffset) { - c.buf.setMedium(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setShort(index, (short) (value >> 8)); - _setByte(index + 2, (byte) value); - } else { - _setShort(index, (short) value); - _setByte(index + 2, (byte) (value >>> 16)); - } - } - - @Override - public CompositeByteBuf setInt(int index, int value) { - return (CompositeByteBuf) super.setInt(index, value); - } - - @Override - protected void _setInt(int index, int value) { - Component c = findComponent(index); - if (index + 4 <= c.endOffset) { - c.buf.setInt(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setShort(index, (short) (value >>> 16)); - _setShort(index + 2, (short) value); - } else { - _setShort(index, (short) value); - _setShort(index + 2, (short) (value >>> 16)); - } - } - - @Override - public CompositeByteBuf setLong(int index, long value) { - return (CompositeByteBuf) super.setLong(index, value); - } - - @Override - protected void _setLong(int index, long value) { - Component c = findComponent(index); - if (index + 8 <= c.endOffset) { - c.buf.setLong(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setInt(index, (int) (value >>> 32)); - _setInt(index + 4, (int) value); - } else { - _setInt(index, (int) value); - _setInt(index + 4, (int) (value >>> 32)); - } - } - - @Override - public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.setBytes(index - adjustment, src, srcIndex, localLength); - index += localLength; - srcIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuffer src) { - int limit = src.limit(); - int length = src.remaining(); - - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - try { - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - src.limit(src.position() + localLength); - s.setBytes(index - adjustment, src); - index += localLength; - length -= localLength; - i ++; - } - } finally { - src.limit(limit); - } - return this; - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.setBytes(index - adjustment, src, srcIndex, localLength); - index += localLength; - srcIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return in.read(EmptyArrays.EMPTY_BYTES); - } - - int i = toComponentIndex(index); - int readBytes = 0; - - do { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - int localReadBytes = s.setBytes(index - adjustment, in, localLength); - if (localReadBytes < 0) { - if (readBytes == 0) { - return -1; - } else { - break; - } - } - - if (localReadBytes == localLength) { - index += localLength; - length -= localLength; - readBytes += localLength; - i ++; - } else { - index += localReadBytes; - length -= localReadBytes; - readBytes += localReadBytes; - } - } while (length > 0); - - return readBytes; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return in.read(FULL_BYTEBUFFER); - } - - int i = toComponentIndex(index); - int readBytes = 0; - do { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - int localReadBytes = s.setBytes(index - adjustment, in, localLength); - - if (localReadBytes == 0) { - break; - } - - if (localReadBytes < 0) { - if (readBytes == 0) { - return -1; - } else { - break; - } - } - - if (localReadBytes == localLength) { - index += localLength; - length -= localLength; - readBytes += localLength; - i ++; - } else { - index += localReadBytes; - length -= localReadBytes; - readBytes += localReadBytes; - } - } while (length > 0); - - return readBytes; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf dst = Unpooled.buffer(length); - if (length != 0) { - copyTo(index, length, toComponentIndex(index), dst); - } - return dst; - } - - private void copyTo(int index, int length, int componentId, ByteBuf dst) { - int dstIndex = 0; - int i = componentId; - - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - - dst.writerIndex(dst.capacity()); - } - - /** - * Return the {@link ByteBuf} on the specified index - * - * @param cIndex the index for which the {@link ByteBuf} should be returned - * @return buf the {@link ByteBuf} on the specified index - */ - public ByteBuf component(int cIndex) { - return internalComponent(cIndex).duplicate(); - } - - /** - * Return the {@link ByteBuf} on the specified index - * - * @param offset the offset for which the {@link ByteBuf} should be returned - * @return the {@link ByteBuf} on the specified index - */ - public ByteBuf componentAtOffset(int offset) { - return internalComponentAtOffset(offset).duplicate(); - } - - /** - * Return the internal {@link ByteBuf} on the specified index. Note that updating the indexes of the returned - * buffer will lead to an undefined behavior of this buffer. - * - * @param cIndex the index for which the {@link ByteBuf} should be returned - */ - public ByteBuf internalComponent(int cIndex) { - checkComponentIndex(cIndex); - return components.get(cIndex).buf; - } - - /** - * Return the internal {@link ByteBuf} on the specified offset. Note that updating the indexes of the returned - * buffer will lead to an undefined behavior of this buffer. - * - * @param offset the offset for which the {@link ByteBuf} should be returned - */ - public ByteBuf internalComponentAtOffset(int offset) { - return findComponent(offset).buf; - } - - private Component findComponent(int offset) { - checkIndex(offset); - - for (int low = 0, high = components.size(); low <= high;) { - int mid = low + high >>> 1; - Component c = components.get(mid); - if (offset >= c.endOffset) { - low = mid + 1; - } else if (offset < c.offset) { - high = mid - 1; - } else { - return c; - } - } - - throw new Error("should not reach here"); - } - - @Override - public int nioBufferCount() { - if (components.size() == 1) { - return components.get(0).buf.nioBufferCount(); - } else { - int count = 0; - int componentsCount = components.size(); - for (int i = 0; i < componentsCount; i++) { - Component c = components.get(i); - count += c.buf.nioBufferCount(); - } - return count; - } - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - if (components.size() == 1) { - return components.get(0).buf.internalNioBuffer(index, length); - } - throw new UnsupportedOperationException(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - if (components.size() == 1) { - ByteBuf buf = components.get(0).buf; - if (buf.nioBufferCount() == 1) { - return components.get(0).buf.nioBuffer(index, length); - } - } - ByteBuffer merged = ByteBuffer.allocate(length).order(order()); - ByteBuffer[] buffers = nioBuffers(index, length); - - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < buffers.length; i++) { - merged.put(buffers[i]); - } - - merged.flip(); - return merged; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - if (length == 0) { - return EmptyArrays.EMPTY_BYTE_BUFFERS; - } - - List buffers = new ArrayList(components.size()); - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - switch (s.nioBufferCount()) { - case 0: - throw new UnsupportedOperationException(); - case 1: - buffers.add(s.nioBuffer(index - adjustment, localLength)); - break; - default: - Collections.addAll(buffers, s.nioBuffers(index - adjustment, localLength)); - } - - index += localLength; - length -= localLength; - i ++; - } - - return buffers.toArray(new ByteBuffer[buffers.size()]); - } - - /** - * Consolidate the composed {@link ByteBuf}s - */ - public CompositeByteBuf consolidate() { - ensureAccessible(); - final int numComponents = numComponents(); - if (numComponents <= 1) { - return this; - } - - final Component last = components.get(numComponents - 1); - final int capacity = last.endOffset; - final ByteBuf consolidated = allocBuffer(capacity); - - for (int i = 0; i < numComponents; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - - components.clear(); - components.add(new Component(consolidated)); - updateComponentOffsets(0); - return this; - } - - /** - * Consolidate the composed {@link ByteBuf}s - * - * @param cIndex the index on which to start to compose - * @param numComponents the number of components to compose - */ - public CompositeByteBuf consolidate(int cIndex, int numComponents) { - checkComponentIndex(cIndex, numComponents); - if (numComponents <= 1) { - return this; - } - - final int endCIndex = cIndex + numComponents; - final Component last = components.get(endCIndex - 1); - final int capacity = last.endOffset - components.get(cIndex).offset; - final ByteBuf consolidated = allocBuffer(capacity); - - for (int i = cIndex; i < endCIndex; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - - components.subList(cIndex + 1, endCIndex).clear(); - components.set(cIndex, new Component(consolidated)); - updateComponentOffsets(cIndex); - return this; - } - - /** - * Discard all {@link ByteBuf}s which are read. - */ - public CompositeByteBuf discardReadComponents() { - ensureAccessible(); - final int readerIndex = readerIndex(); - if (readerIndex == 0) { - return this; - } - - // Discard everything if (readerIndex = writerIndex = capacity). - int writerIndex = writerIndex(); - if (readerIndex == writerIndex && writerIndex == capacity()) { - for (Component c: components) { - c.freeIfNecessary(); - } - components.clear(); - setIndex(0, 0); - adjustMarkers(readerIndex); - return this; - } - - // Remove read components. - int firstComponentId = toComponentIndex(readerIndex); - for (int i = 0; i < firstComponentId; i ++) { - components.get(i).freeIfNecessary(); - } - components.subList(0, firstComponentId).clear(); - - // Update indexes and markers. - Component first = components.get(0); - int offset = first.offset; - updateComponentOffsets(0); - setIndex(readerIndex - offset, writerIndex - offset); - adjustMarkers(offset); - return this; - } - - @Override - public CompositeByteBuf discardReadBytes() { - ensureAccessible(); - final int readerIndex = readerIndex(); - if (readerIndex == 0) { - return this; - } - - // Discard everything if (readerIndex = writerIndex = capacity). - int writerIndex = writerIndex(); - if (readerIndex == writerIndex && writerIndex == capacity()) { - for (Component c: components) { - c.freeIfNecessary(); - } - components.clear(); - setIndex(0, 0); - adjustMarkers(readerIndex); - return this; - } - - // Remove read components. - int firstComponentId = toComponentIndex(readerIndex); - for (int i = 0; i < firstComponentId; i ++) { - components.get(i).freeIfNecessary(); - } - components.subList(0, firstComponentId).clear(); - - // Remove or replace the first readable component with a new slice. - Component c = components.get(0); - int adjustment = readerIndex - c.offset; - if (adjustment == c.length) { - // new slice would be empty, so remove instead - components.remove(0); - } else { - Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment)); - components.set(0, newC); - } - - // Update indexes and markers. - updateComponentOffsets(0); - setIndex(0, writerIndex - readerIndex); - adjustMarkers(readerIndex); - return this; - } - - private ByteBuf allocBuffer(int capacity) { - if (direct) { - return alloc().directBuffer(capacity); - } - return alloc().heapBuffer(capacity); - } - - @Override - public String toString() { - String result = super.toString(); - result = result.substring(0, result.length() - 1); - return result + ", components=" + components.size() + ')'; - } - - private static final class Component { - final ByteBuf buf; - final int length; - int offset; - int endOffset; - - Component(ByteBuf buf) { - this.buf = buf; - length = buf.readableBytes(); - } - - void freeIfNecessary() { - // Unwrap so that we can free slices, too. - buf.release(); // We should not get a NPE here. If so, it must be a bug. - } - } - - @Override - public CompositeByteBuf readerIndex(int readerIndex) { - return (CompositeByteBuf) super.readerIndex(readerIndex); - } - - @Override - public CompositeByteBuf writerIndex(int writerIndex) { - return (CompositeByteBuf) super.writerIndex(writerIndex); - } - - @Override - public CompositeByteBuf setIndex(int readerIndex, int writerIndex) { - return (CompositeByteBuf) super.setIndex(readerIndex, writerIndex); - } - - @Override - public CompositeByteBuf clear() { - return (CompositeByteBuf) super.clear(); - } - - @Override - public CompositeByteBuf markReaderIndex() { - return (CompositeByteBuf) super.markReaderIndex(); - } - - @Override - public CompositeByteBuf resetReaderIndex() { - return (CompositeByteBuf) super.resetReaderIndex(); - } - - @Override - public CompositeByteBuf markWriterIndex() { - return (CompositeByteBuf) super.markWriterIndex(); - } - - @Override - public CompositeByteBuf resetWriterIndex() { - return (CompositeByteBuf) super.resetWriterIndex(); - } - - @Override - public CompositeByteBuf ensureWritable(int minWritableBytes) { - return (CompositeByteBuf) super.ensureWritable(minWritableBytes); - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst) { - return (CompositeByteBuf) super.getBytes(index, dst); - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) { - return (CompositeByteBuf) super.getBytes(index, dst, length); - } - - @Override - public CompositeByteBuf getBytes(int index, byte[] dst) { - return (CompositeByteBuf) super.getBytes(index, dst); - } - - @Override - public CompositeByteBuf setBoolean(int index, boolean value) { - return (CompositeByteBuf) super.setBoolean(index, value); - } - - @Override - public CompositeByteBuf setChar(int index, int value) { - return (CompositeByteBuf) super.setChar(index, value); - } - - @Override - public CompositeByteBuf setFloat(int index, float value) { - return (CompositeByteBuf) super.setFloat(index, value); - } - - @Override - public CompositeByteBuf setDouble(int index, double value) { - return (CompositeByteBuf) super.setDouble(index, value); - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src) { - return (CompositeByteBuf) super.setBytes(index, src); - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src, int length) { - return (CompositeByteBuf) super.setBytes(index, src, length); - } - - @Override - public CompositeByteBuf setBytes(int index, byte[] src) { - return (CompositeByteBuf) super.setBytes(index, src); - } - - @Override - public CompositeByteBuf setZero(int index, int length) { - return (CompositeByteBuf) super.setZero(index, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst, int length) { - return (CompositeByteBuf) super.readBytes(dst, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); - } - - @Override - public CompositeByteBuf readBytes(byte[] dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) { - return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuffer dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException { - return (CompositeByteBuf) super.readBytes(out, length); - } - - @Override - public CompositeByteBuf skipBytes(int length) { - return (CompositeByteBuf) super.skipBytes(length); - } - - @Override - public CompositeByteBuf writeBoolean(boolean value) { - return (CompositeByteBuf) super.writeBoolean(value); - } - - @Override - public CompositeByteBuf writeByte(int value) { - return (CompositeByteBuf) super.writeByte(value); - } - - @Override - public CompositeByteBuf writeShort(int value) { - return (CompositeByteBuf) super.writeShort(value); - } - - @Override - public CompositeByteBuf writeMedium(int value) { - return (CompositeByteBuf) super.writeMedium(value); - } - - @Override - public CompositeByteBuf writeInt(int value) { - return (CompositeByteBuf) super.writeInt(value); - } - - @Override - public CompositeByteBuf writeLong(long value) { - return (CompositeByteBuf) super.writeLong(value); - } - - @Override - public CompositeByteBuf writeChar(int value) { - return (CompositeByteBuf) super.writeChar(value); - } - - @Override - public CompositeByteBuf writeFloat(float value) { - return (CompositeByteBuf) super.writeFloat(value); - } - - @Override - public CompositeByteBuf writeDouble(double value) { - return (CompositeByteBuf) super.writeDouble(value); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src, int length) { - return (CompositeByteBuf) super.writeBytes(src, length); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); - } - - @Override - public CompositeByteBuf writeBytes(byte[] src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) { - return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuffer src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeZero(int length) { - return (CompositeByteBuf) super.writeZero(length); - } - - @Override - public CompositeByteBuf retain(int increment) { - return (CompositeByteBuf) super.retain(increment); - } - - @Override - public CompositeByteBuf retain() { - return (CompositeByteBuf) super.retain(); - } - - @Override - public ByteBuffer[] nioBuffers() { - return nioBuffers(readerIndex(), readableBytes()); - } - - @Override - public CompositeByteBuf discardSomeReadBytes() { - return discardReadComponents(); - } - - @Override - protected void deallocate() { - if (freed) { - return; - } - - freed = true; - int size = components.size(); - // We're not using foreach to avoid creating an iterator. - // see https://github.com/netty/netty/issues/2642 - for (int i = 0; i < size; i++) { - components.get(i).freeIfNecessary(); - } - - if (leak != null) { - leak.close(); - } - } - - @Override - public ByteBuf unwrap() { - return null; - } -} diff --git a/java/src/game/net/buffer/DuplicatedByteBuf.java b/java/src/game/net/buffer/DuplicatedByteBuf.java deleted file mode 100644 index e67ef3d..0000000 --- a/java/src/game/net/buffer/DuplicatedByteBuf.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - - -/** - * A derived buffer which simply forwards all data access requests to its - * parent. It is recommended to use {@link ByteBuf#duplicate()} instead - * of calling the constructor explicitly. - */ -public class DuplicatedByteBuf extends AbstractDerivedByteBuf { - - private final ByteBuf buffer; - - public DuplicatedByteBuf(ByteBuf buffer) { - super(buffer.maxCapacity()); - - if (buffer instanceof DuplicatedByteBuf) { - this.buffer = ((DuplicatedByteBuf) buffer).buffer; - } else { - this.buffer = buffer; - } - - setIndex(buffer.readerIndex(), buffer.writerIndex()); - } - - @Override - public ByteBuf unwrap() { - return buffer; - } - - @Override - public ByteBufAllocator alloc() { - return buffer.alloc(); - } - - @Override - public ByteOrder order() { - return buffer.order(); - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public int capacity() { - return buffer.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - buffer.capacity(newCapacity); - return this; - } - - @Override - public boolean hasArray() { - return buffer.hasArray(); - } - - @Override - public byte[] array() { - return buffer.array(); - } - - @Override - public int arrayOffset() { - return buffer.arrayOffset(); - } - - @Override - public boolean hasMemoryAddress() { - return buffer.hasMemoryAddress(); - } - - @Override - public long memoryAddress() { - return buffer.memoryAddress(); - } - - @Override - public byte getByte(int index) { - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.getByte(index); - } - - @Override - public short getShort(int index) { - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return buffer.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public ByteBuf copy(int index, int length) { - return buffer.copy(index, length); - } - - @Override - public ByteBuf slice(int index, int length) { - return buffer.slice(index, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buffer.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - _setByte(index, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - buffer.setByte(index, value); - } - - @Override - public ByteBuf setShort(int index, int value) { - _setShort(index, value); - return this; - } - - @Override - protected void _setShort(int index, int value) { - buffer.setShort(index, value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - _setMedium(index, value); - return this; - } - - @Override - protected void _setMedium(int index, int value) { - buffer.setMedium(index, value); - } - - @Override - public ByteBuf setInt(int index, int value) { - _setInt(index, value); - return this; - } - - @Override - protected void _setInt(int index, int value) { - buffer.setInt(index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - _setLong(index, value); - return this; - } - - @Override - protected void _setLong(int index, long value) { - buffer.setLong(index, value); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - buffer.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - buffer.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - buffer.setBytes(index, src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) - throws IOException { - buffer.getBytes(index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - return buffer.getBytes(index, out, length); - } - - @Override - public int setBytes(int index, InputStream in, int length) - throws IOException { - return buffer.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) - throws IOException { - return buffer.setBytes(index, in, length); - } - - @Override - public int nioBufferCount() { - return buffer.nioBufferCount(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return buffer.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByteDesc(index, length, processor); - } -} - diff --git a/java/src/game/net/buffer/EmptyByteBuf.java b/java/src/game/net/buffer/EmptyByteBuf.java deleted file mode 100644 index 4917eea..0000000 --- a/java/src/game/net/buffer/EmptyByteBuf.java +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import game.net.util.internal.EmptyArrays; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.StringUtil; - -/** - * An empty {@link ByteBuf} whose capacity and maximum capacity are all {@code 0}. - */ -public final class EmptyByteBuf extends ByteBuf { - - private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0); - private static final long EMPTY_BYTE_BUFFER_ADDRESS; - - static { - long emptyByteBufferAddress = 0; - try { - if (PlatformDependent.hasUnsafe()) { - emptyByteBufferAddress = PlatformDependent.directBufferAddress(EMPTY_BYTE_BUFFER); - } - } catch (Throwable t) { - // Ignore - } - EMPTY_BYTE_BUFFER_ADDRESS = emptyByteBufferAddress; - } - - private final ByteBufAllocator alloc; - private final ByteOrder order; - private final String str; - private EmptyByteBuf swapped; - - public EmptyByteBuf(ByteBufAllocator alloc) { - this(alloc, ByteOrder.BIG_ENDIAN); - } - - private EmptyByteBuf(ByteBufAllocator alloc, ByteOrder order) { - if (alloc == null) { - throw new NullPointerException("alloc"); - } - - this.alloc = alloc; - this.order = order; - str = StringUtil.simpleClassName(this) + (order == ByteOrder.BIG_ENDIAN? "BE" : "LE"); - } - - @Override - public int capacity() { - return 0; - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return order; - } - - @Override - public ByteBuf unwrap() { - return null; - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - public int maxCapacity() { - return 0; - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order()) { - return this; - } - - EmptyByteBuf swapped = this.swapped; - if (swapped != null) { - return swapped; - } - - this.swapped = swapped = new EmptyByteBuf(alloc(), endianness); - return swapped; - } - - @Override - public int readerIndex() { - return 0; - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - return checkIndex(readerIndex); - } - - @Override - public int writerIndex() { - return 0; - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - return checkIndex(writerIndex); - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - checkIndex(readerIndex); - checkIndex(writerIndex); - return this; - } - - @Override - public int readableBytes() { - return 0; - } - - @Override - public int writableBytes() { - return 0; - } - - @Override - public int maxWritableBytes() { - return 0; - } - - @Override - public boolean isReadable() { - return false; - } - - @Override - public boolean isWritable() { - return false; - } - - @Override - public ByteBuf clear() { - return this; - } - - @Override - public ByteBuf markReaderIndex() { - return this; - } - - @Override - public ByteBuf resetReaderIndex() { - return this; - } - - @Override - public ByteBuf markWriterIndex() { - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - return this; - } - - @Override - public ByteBuf discardReadBytes() { - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - return this; - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException("minWritableBytes: " + minWritableBytes + " (expected: >= 0)"); - } - if (minWritableBytes != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException("minWritableBytes: " + minWritableBytes + " (expected: >= 0)"); - } - - if (minWritableBytes == 0) { - return 0; - } - - return 1; - } - - @Override - public boolean getBoolean(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public byte getByte(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public short getUnsignedByte(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public short getShort(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getUnsignedShort(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getMedium(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getUnsignedMedium(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getInt(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public long getUnsignedInt(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public long getLong(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public char getChar(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public float getFloat(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public double getDouble(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - return checkIndex(index, dst.writableBytes()); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - return checkIndex(index, dst.length); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - return checkIndex(index, dst.remaining()); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) { - return checkIndex(index, length); - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) { - checkIndex(index, length); - return 0; - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setByte(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setShort(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setMedium(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setInt(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setLong(int index, long value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setChar(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setFloat(int index, float value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setDouble(int index, double value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - return checkIndex(index, src.length); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - return checkIndex(index, src.remaining()); - } - - @Override - public int setBytes(int index, InputStream in, int length) { - checkIndex(index, length); - return 0; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) { - checkIndex(index, length); - return 0; - } - - @Override - public ByteBuf setZero(int index, int length) { - return checkIndex(index, length); - } - - @Override - public boolean readBoolean() { - throw new IndexOutOfBoundsException(); - } - - @Override - public byte readByte() { - throw new IndexOutOfBoundsException(); - } - - @Override - public short readUnsignedByte() { - throw new IndexOutOfBoundsException(); - } - - @Override - public short readShort() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readUnsignedShort() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readMedium() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readUnsignedMedium() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readInt() { - throw new IndexOutOfBoundsException(); - } - - @Override - public long readUnsignedInt() { - throw new IndexOutOfBoundsException(); - } - - @Override - public long readLong() { - throw new IndexOutOfBoundsException(); - } - - @Override - public char readChar() { - throw new IndexOutOfBoundsException(); - } - - @Override - public float readFloat() { - throw new IndexOutOfBoundsException(); - } - - @Override - public double readDouble() { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf readBytes(int length) { - return checkLength(length); - } - - @Override - public ByteBuf readSlice(int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - return checkLength(dst.writableBytes()); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(byte[] dst) { - return checkLength(dst.length); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - return checkLength(dst.remaining()); - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) { - return checkLength(length); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) { - checkLength(length); - return 0; - } - - @Override - public ByteBuf skipBytes(int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBoolean(boolean value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeByte(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeShort(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeMedium(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeInt(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeLong(long value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeChar(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeFloat(float value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeDouble(double value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBytes(byte[] src) { - return checkLength(src.length); - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - return checkLength(src.remaining()); - } - - @Override - public int writeBytes(InputStream in, int length) { - checkLength(length); - return 0; - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) { - checkLength(length); - return 0; - } - - @Override - public ByteBuf writeZero(int length) { - return checkLength(length); - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - checkIndex(fromIndex); - checkIndex(toIndex); - return -1; - } - - @Override - public int bytesBefore(byte value) { - return -1; - } - - @Override - public int bytesBefore(int length, byte value) { - checkLength(length); - return -1; - } - - @Override - public int bytesBefore(int index, int length, byte value) { - checkIndex(index, length); - return -1; - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - return -1; - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - return -1; - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - return -1; - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - return -1; - } - - @Override - public ByteBuf copy() { - return this; - } - - @Override - public ByteBuf copy(int index, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf slice() { - return this; - } - - @Override - public ByteBuf slice(int index, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf duplicate() { - return this; - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer nioBuffer() { - return EMPTY_BYTE_BUFFER; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return nioBuffer(); - } - - @Override - public ByteBuffer[] nioBuffers() { - return new ByteBuffer[] { EMPTY_BYTE_BUFFER }; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - return nioBuffers(); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return EMPTY_BYTE_BUFFER; - } - - @Override - public boolean hasArray() { - return true; - } - - @Override - public byte[] array() { - return EmptyArrays.EMPTY_BYTES; - } - - @Override - public int arrayOffset() { - return 0; - } - - @Override - public boolean hasMemoryAddress() { - return EMPTY_BYTE_BUFFER_ADDRESS != 0; - } - - @Override - public long memoryAddress() { - if (hasMemoryAddress()) { - return EMPTY_BYTE_BUFFER_ADDRESS; - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public String toString(Charset charset) { - return ""; - } - - @Override - public String toString(int index, int length, Charset charset) { - checkIndex(index, length); - return toString(charset); - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof ByteBuf && !((ByteBuf) obj).isReadable(); - } - - @Override - public int compareTo(ByteBuf buffer) { - return buffer.isReadable()? -1 : 0; - } - - @Override - public String toString() { - return str; - } - - @Override - public boolean isReadable(int size) { - return false; - } - - @Override - public boolean isWritable(int size) { - return false; - } - - @Override - public int refCnt() { - return 1; - } - - @Override - public ByteBuf retain() { - return this; - } - - @Override - public ByteBuf retain(int increment) { - return this; - } - - @Override - public boolean release() { - return false; - } - - @Override - public boolean release(int decrement) { - return false; - } - - private ByteBuf checkIndex(int index) { - if (index != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } - - private ByteBuf checkIndex(int index, int length) { - if (length < 0) { - throw new IllegalArgumentException("length: " + length); - } - if (index != 0 || length != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } - - private ByteBuf checkLength(int length) { - if (length < 0) { - throw new IllegalArgumentException("length: " + length + " (expected: >= 0)"); - } - if (length != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } -} diff --git a/java/src/game/net/buffer/PoolArena.java b/java/src/game/net/buffer/PoolArena.java deleted file mode 100644 index 4837ecd..0000000 --- a/java/src/game/net/buffer/PoolArena.java +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.nio.ByteBuffer; - -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.StringUtil; - -abstract class PoolArena { - - static final int numTinySubpagePools = 512 >>> 4; - - final PooledByteBufAllocator parent; - - private final int maxOrder; - final int pageSize; - final int pageShifts; - final int chunkSize; - final int subpageOverflowMask; - final int numSmallSubpagePools; - private final PoolSubpage[] tinySubpagePools; - private final PoolSubpage[] smallSubpagePools; - - private final PoolChunkList q050; - private final PoolChunkList q025; - private final PoolChunkList q000; - private final PoolChunkList qInit; - private final PoolChunkList q075; - private final PoolChunkList q100; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - protected PoolArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - this.parent = parent; - this.pageSize = pageSize; - this.maxOrder = maxOrder; - this.pageShifts = pageShifts; - this.chunkSize = chunkSize; - subpageOverflowMask = ~(pageSize - 1); - tinySubpagePools = newSubpagePoolArray(numTinySubpagePools); - for (int i = 0; i < tinySubpagePools.length; i ++) { - tinySubpagePools[i] = newSubpagePoolHead(pageSize); - } - - numSmallSubpagePools = pageShifts - 9; - smallSubpagePools = newSubpagePoolArray(numSmallSubpagePools); - for (int i = 0; i < smallSubpagePools.length; i ++) { - smallSubpagePools[i] = newSubpagePoolHead(pageSize); - } - - q100 = new PoolChunkList(this, null, 100, Integer.MAX_VALUE); - q075 = new PoolChunkList(this, q100, 75, 100); - q050 = new PoolChunkList(this, q075, 50, 100); - q025 = new PoolChunkList(this, q050, 25, 75); - q000 = new PoolChunkList(this, q025, 1, 50); - qInit = new PoolChunkList(this, q000, Integer.MIN_VALUE, 25); - - q100.prevList = q075; - q075.prevList = q050; - q050.prevList = q025; - q025.prevList = q000; - q000.prevList = null; - qInit.prevList = qInit; - } - - private PoolSubpage newSubpagePoolHead(int pageSize) { - PoolSubpage head = new PoolSubpage(pageSize); - head.prev = head; - head.next = head; - return head; - } - - - private PoolSubpage[] newSubpagePoolArray(int size) { - return new PoolSubpage[size]; - } - - abstract boolean isDirect(); - - PooledByteBuf allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) { - PooledByteBuf buf = newByteBuf(maxCapacity); - allocate(cache, buf, reqCapacity); - return buf; - } - - static int tinyIdx(int normCapacity) { - return normCapacity >>> 4; - } - - static int smallIdx(int normCapacity) { - int tableIdx = 0; - int i = normCapacity >>> 10; - while (i != 0) { - i >>>= 1; - tableIdx ++; - } - return tableIdx; - } - - // capacity < pageSize - boolean isTinyOrSmall(int normCapacity) { - return (normCapacity & subpageOverflowMask) == 0; - } - - // normCapacity < 512 - static boolean isTiny(int normCapacity) { - return (normCapacity & 0xFFFFFE00) == 0; - } - - private void allocate(PoolThreadCache cache, PooledByteBuf buf, final int reqCapacity) { - final int normCapacity = normalizeCapacity(reqCapacity); - if (isTinyOrSmall(normCapacity)) { // capacity < pageSize - int tableIdx; - PoolSubpage[] table; - if (isTiny(normCapacity)) { // < 512 - if (cache.allocateTiny(this, buf, reqCapacity, normCapacity)) { - // was able to allocate out of the cache so move on - return; - } - tableIdx = tinyIdx(normCapacity); - table = tinySubpagePools; - } else { - if (cache.allocateSmall(this, buf, reqCapacity, normCapacity)) { - // was able to allocate out of the cache so move on - return; - } - tableIdx = smallIdx(normCapacity); - table = smallSubpagePools; - } - - synchronized (this) { - final PoolSubpage head = table[tableIdx]; - final PoolSubpage s = head.next; - if (s != head) { - assert s.doNotDestroy && s.elemSize == normCapacity; - long handle = s.allocate(); - assert handle >= 0; - s.chunk.initBufWithSubpage(buf, handle, reqCapacity); - return; - } - } - } else if (normCapacity <= chunkSize) { - if (cache.allocateNormal(this, buf, reqCapacity, normCapacity)) { - // was able to allocate out of the cache so move on - return; - } - } else { - // Huge allocations are never served via the cache so just call allocateHuge - allocateHuge(buf, reqCapacity); - return; - } - allocateNormal(buf, reqCapacity, normCapacity); - } - - private synchronized void allocateNormal(PooledByteBuf buf, int reqCapacity, int normCapacity) { - if (q050.allocate(buf, reqCapacity, normCapacity) || q025.allocate(buf, reqCapacity, normCapacity) || - q000.allocate(buf, reqCapacity, normCapacity) || qInit.allocate(buf, reqCapacity, normCapacity) || - q075.allocate(buf, reqCapacity, normCapacity) || q100.allocate(buf, reqCapacity, normCapacity)) { - return; - } - - // Add a new chunk. - PoolChunk c = newChunk(pageSize, maxOrder, pageShifts, chunkSize); - long handle = c.allocate(normCapacity); - assert handle > 0; - c.initBuf(buf, handle, reqCapacity); - qInit.add(c); - } - - private void allocateHuge(PooledByteBuf buf, int reqCapacity) { - buf.initUnpooled(newUnpooledChunk(reqCapacity), reqCapacity); - } - - void free(PoolChunk chunk, long handle, int normCapacity) { - if (chunk.unpooled) { - destroyChunk(chunk); - } else { - PoolThreadCache cache = parent.threadCache.get(); - if (cache.add(this, chunk, handle, normCapacity)) { - // cached so not free it. - return; - } - synchronized (this) { - chunk.parent.free(chunk, handle); - } - } - } - - PoolSubpage findSubpagePoolHead(int elemSize) { - int tableIdx; - PoolSubpage[] table; - if (isTiny(elemSize)) { // < 512 - tableIdx = elemSize >>> 4; - table = tinySubpagePools; - } else { - tableIdx = 0; - elemSize >>>= 10; - while (elemSize != 0) { - elemSize >>>= 1; - tableIdx ++; - } - table = smallSubpagePools; - } - - return table[tableIdx]; - } - - int normalizeCapacity(int reqCapacity) { - if (reqCapacity < 0) { - throw new IllegalArgumentException("capacity: " + reqCapacity + " (expected: 0+)"); - } - if (reqCapacity >= chunkSize) { - return reqCapacity; - } - - if (!isTiny(reqCapacity)) { // >= 512 - // Doubled - - int normalizedCapacity = reqCapacity; - normalizedCapacity --; - normalizedCapacity |= normalizedCapacity >>> 1; - normalizedCapacity |= normalizedCapacity >>> 2; - normalizedCapacity |= normalizedCapacity >>> 4; - normalizedCapacity |= normalizedCapacity >>> 8; - normalizedCapacity |= normalizedCapacity >>> 16; - normalizedCapacity ++; - - if (normalizedCapacity < 0) { - normalizedCapacity >>>= 1; - } - - return normalizedCapacity; - } - - // Quantum-spaced - if ((reqCapacity & 15) == 0) { - return reqCapacity; - } - - return (reqCapacity & ~15) + 16; - } - - void reallocate(PooledByteBuf buf, int newCapacity, boolean freeOldMemory) { - if (newCapacity < 0 || newCapacity > buf.maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int oldCapacity = buf.length; - if (oldCapacity == newCapacity) { - return; - } - - PoolChunk oldChunk = buf.chunk; - long oldHandle = buf.handle; - T oldMemory = buf.memory; - int oldOffset = buf.offset; - int oldMaxLength = buf.maxLength; - int readerIndex = buf.readerIndex(); - int writerIndex = buf.writerIndex(); - - allocate(parent.threadCache.get(), buf, newCapacity); - if (newCapacity > oldCapacity) { - memoryCopy( - oldMemory, oldOffset, - buf.memory, buf.offset, oldCapacity); - } else if (newCapacity < oldCapacity) { - if (readerIndex < newCapacity) { - if (writerIndex > newCapacity) { - writerIndex = newCapacity; - } - memoryCopy( - oldMemory, oldOffset + readerIndex, - buf.memory, buf.offset + readerIndex, writerIndex - readerIndex); - } else { - readerIndex = writerIndex = newCapacity; - } - } - - buf.setIndex(readerIndex, writerIndex); - - if (freeOldMemory) { - free(oldChunk, oldHandle, oldMaxLength); - } - } - - protected abstract PoolChunk newChunk(int pageSize, int maxOrder, int pageShifts, int chunkSize); - protected abstract PoolChunk newUnpooledChunk(int capacity); - protected abstract PooledByteBuf newByteBuf(int maxCapacity); - protected abstract void memoryCopy(T src, int srcOffset, T dst, int dstOffset, int length); - protected abstract void destroyChunk(PoolChunk chunk); - - public synchronized String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("Chunk(s) at 0~25%:"); - buf.append(StringUtil.NEWLINE); - buf.append(qInit); - buf.append(StringUtil.NEWLINE); - buf.append("Chunk(s) at 0~50%:"); - buf.append(StringUtil.NEWLINE); - buf.append(q000); - buf.append(StringUtil.NEWLINE); - buf.append("Chunk(s) at 25~75%:"); - buf.append(StringUtil.NEWLINE); - buf.append(q025); - buf.append(StringUtil.NEWLINE); - buf.append("Chunk(s) at 50~100%:"); - buf.append(StringUtil.NEWLINE); - buf.append(q050); - buf.append(StringUtil.NEWLINE); - buf.append("Chunk(s) at 75~100%:"); - buf.append(StringUtil.NEWLINE); - buf.append(q075); - buf.append(StringUtil.NEWLINE); - buf.append("Chunk(s) at 100%:"); - buf.append(StringUtil.NEWLINE); - buf.append(q100); - buf.append(StringUtil.NEWLINE); - buf.append("tiny subpages:"); - for (int i = 1; i < tinySubpagePools.length; i ++) { - PoolSubpage head = tinySubpagePools[i]; - if (head.next == head) { - continue; - } - - buf.append(StringUtil.NEWLINE); - buf.append(i); - buf.append(": "); - PoolSubpage s = head.next; - for (;;) { - buf.append(s); - s = s.next; - if (s == head) { - break; - } - } - } - buf.append(StringUtil.NEWLINE); - buf.append("small subpages:"); - for (int i = 1; i < smallSubpagePools.length; i ++) { - PoolSubpage head = smallSubpagePools[i]; - if (head.next == head) { - continue; - } - - buf.append(StringUtil.NEWLINE); - buf.append(i); - buf.append(": "); - PoolSubpage s = head.next; - for (;;) { - buf.append(s); - s = s.next; - if (s == head) { - break; - } - } - } - buf.append(StringUtil.NEWLINE); - - return buf.toString(); - } - - static final class HeapArena extends PoolArena { - - HeapArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - super(parent, pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - boolean isDirect() { - return false; - } - - @Override - protected PoolChunk newChunk(int pageSize, int maxOrder, int pageShifts, int chunkSize) { - return new PoolChunk(this, new byte[chunkSize], pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - protected PoolChunk newUnpooledChunk(int capacity) { - return new PoolChunk(this, new byte[capacity], capacity); - } - - @Override - protected void destroyChunk(PoolChunk chunk) { - // Rely on GC. - } - - @Override - protected PooledByteBuf newByteBuf(int maxCapacity) { - return PooledHeapByteBuf.newInstance(maxCapacity); - } - - @Override - protected void memoryCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int length) { - if (length == 0) { - return; - } - - System.arraycopy(src, srcOffset, dst, dstOffset, length); - } - } - - static final class DirectArena extends PoolArena { - - private static final boolean HAS_UNSAFE = PlatformDependent.hasUnsafe(); - - DirectArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - super(parent, pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - boolean isDirect() { - return true; - } - - @Override - protected PoolChunk newChunk(int pageSize, int maxOrder, int pageShifts, int chunkSize) { - return new PoolChunk( - this, ByteBuffer.allocateDirect(chunkSize), pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - protected PoolChunk newUnpooledChunk(int capacity) { - return new PoolChunk(this, ByteBuffer.allocateDirect(capacity), capacity); - } - - @Override - protected void destroyChunk(PoolChunk chunk) { - PlatformDependent.freeDirectBuffer(chunk.memory); - } - - @Override - protected PooledByteBuf newByteBuf(int maxCapacity) { - if (HAS_UNSAFE) { - return PooledUnsafeDirectByteBuf.newInstance(maxCapacity); - } else { - return PooledDirectByteBuf.newInstance(maxCapacity); - } - } - - @Override - protected void memoryCopy(ByteBuffer src, int srcOffset, ByteBuffer dst, int dstOffset, int length) { - if (length == 0) { - return; - } - - if (HAS_UNSAFE) { - PlatformDependent.copyMemory( - PlatformDependent.directBufferAddress(src) + srcOffset, - PlatformDependent.directBufferAddress(dst) + dstOffset, length); - } else { - // We must duplicate the NIO buffers because they may be accessed by other Netty buffers. - src = src.duplicate(); - dst = dst.duplicate(); - src.position(srcOffset).limit(srcOffset + length); - dst.position(dstOffset); - dst.put(src); - } - } - } -} diff --git a/java/src/game/net/buffer/PoolChunk.java b/java/src/game/net/buffer/PoolChunk.java deleted file mode 100644 index d0b29ac..0000000 --- a/java/src/game/net/buffer/PoolChunk.java +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -/** - * Description of algorithm for PageRun/PoolSubpage allocation from PoolChunk - * - * Notation: The following terms are important to understand the code - * > page - a page is the smallest unit of memory chunk that can be allocated - * > chunk - a chunk is a collection of pages - * > in this code chunkSize = 2^{maxOrder} * pageSize - * - * To begin we allocate a byte array of size = chunkSize - * Whenever a ByteBuf of given size needs to be created we search for the first position - * in the byte array that has enough empty space to accommodate the requested size and - * return a (long) handle that encodes this offset information, (this memory segment is then - * marked as reserved so it is always used by exactly one ByteBuf and no more) - * - * For simplicity all sizes are normalized according to PoolArena#normalizeCapacity method - * This ensures that when we request for memory segments of size >= pageSize the normalizedCapacity - * equals the next nearest power of 2 - * - * To search for the first offset in chunk that has at least requested size available we construct a - * complete balanced binary tree and store it in an array (just like heaps) - memoryMap - * - * The tree looks like this (the size of each node being mentioned in the parenthesis) - * - * depth=0 1 node (chunkSize) - * depth=1 2 nodes (chunkSize/2) - * .. - * .. - * depth=d 2^d nodes (chunkSize/2^d) - * .. - * depth=maxOrder 2^maxOrder nodes (chunkSize/2^{maxOrder} = pageSize) - * - * depth=maxOrder is the last level and the leafs consist of pages - * - * With this tree available searching in chunkArray translates like this: - * To allocate a memory segment of size chunkSize/2^k we search for the first node (from left) at height k - * which is unused - * - * Algorithm: - * ---------- - * Encode the tree in memoryMap with the notation - * memoryMap[id] = x => in the subtree rooted at id, the first node that is free to be allocated - * is at depth x (counted from depth=0) i.e., at depths [depth_of_id, x), there is no node that is free - * - * As we allocate & free nodes, we update values stored in memoryMap so that the property is maintained - * - * Initialization - - * In the beginning we construct the memoryMap array by storing the depth of a node at each node - * i.e., memoryMap[id] = depth_of_id - * - * Observations: - * ------------- - * 1) memoryMap[id] = depth_of_id => it is free / unallocated - * 2) memoryMap[id] > depth_of_id => at least one of its child nodes is allocated, so we cannot allocate it, but - * some of its children can still be allocated based on their availability - * 3) memoryMap[id] = maxOrder + 1 => the node is fully allocated & thus none of its children can be allocated, it - * is thus marked as unusable - * - * Algorithm: [allocateNode(d) => we want to find the first node (from left) at height h that can be allocated] - * ---------- - * 1) start at root (i.e., depth = 0 or id = 1) - * 2) if memoryMap[1] > d => cannot be allocated from this chunk - * 3) if left node value <= h; we can allocate from left subtree so move to left and repeat until found - * 4) else try in right subtree - * - * Algorithm: [allocateRun(size)] - * ---------- - * 1) Compute d = log_2(chunkSize/size) - * 2) Return allocateNode(d) - * - * Algorithm: [allocateSubpage(size)] - * ---------- - * 1) use allocateNode(maxOrder) to find an empty (i.e., unused) leaf (i.e., page) - * 2) use this handle to construct the PoolSubpage object or if it already exists just call init(normCapacity) - * note that this PoolSubpage object is added to subpagesPool in the PoolArena when we init() it - * - * Note: - * ----- - * In the implementation for improving cache coherence, - * we store 2 pieces of information (i.e, 2 byte vals) as a short value in memoryMap - * - * memoryMap[id]= (depth_of_id, x) - * where as per convention defined above - * the second value (i.e, x) indicates that the first node which is free to be allocated is at depth x (from root) - */ - -final class PoolChunk { - - final PoolArena arena; - final T memory; - final boolean unpooled; - - private final byte[] memoryMap; - private final byte[] depthMap; - private final PoolSubpage[] subpages; - /** Used to determine if the requested capacity is equal to or greater than pageSize. */ - private final int subpageOverflowMask; - private final int pageSize; - private final int pageShifts; - private final int maxOrder; - private final int chunkSize; - private final int log2ChunkSize; - private final int maxSubpageAllocs; - /** Used to mark memory as unusable */ - private final byte unusable; - - private int freeBytes; - - PoolChunkList parent; - PoolChunk prev; - PoolChunk next; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - PoolChunk(PoolArena arena, T memory, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - unpooled = false; - this.arena = arena; - this.memory = memory; - this.pageSize = pageSize; - this.pageShifts = pageShifts; - this.maxOrder = maxOrder; - this.chunkSize = chunkSize; - unusable = (byte) (maxOrder + 1); - log2ChunkSize = log2(chunkSize); - subpageOverflowMask = ~(pageSize - 1); - freeBytes = chunkSize; - - assert maxOrder < 30 : "maxOrder should be < 30, but is: " + maxOrder; - maxSubpageAllocs = 1 << maxOrder; - - // Generate the memory map. - memoryMap = new byte[maxSubpageAllocs << 1]; - depthMap = new byte[memoryMap.length]; - int memoryMapIndex = 1; - for (int d = 0; d <= maxOrder; ++ d) { // move down the tree one level at a time - int depth = 1 << d; - for (int p = 0; p < depth; ++ p) { - // in each level traverse left to right and set value to the depth of subtree - memoryMap[memoryMapIndex] = (byte) d; - depthMap[memoryMapIndex] = (byte) d; - memoryMapIndex ++; - } - } - - subpages = newSubpageArray(maxSubpageAllocs); - } - - /** Creates a special chunk that is not pooled. */ - PoolChunk(PoolArena arena, T memory, int size) { - unpooled = true; - this.arena = arena; - this.memory = memory; - memoryMap = null; - depthMap = null; - subpages = null; - subpageOverflowMask = 0; - pageSize = 0; - pageShifts = 0; - maxOrder = 0; - unusable = (byte) (maxOrder + 1); - chunkSize = size; - log2ChunkSize = log2(chunkSize); - maxSubpageAllocs = 0; - } - - - private PoolSubpage[] newSubpageArray(int size) { - return new PoolSubpage[size]; - } - - int usage() { - final int freeBytes = this.freeBytes; - if (freeBytes == 0) { - return 100; - } - - int freePercentage = (int) (freeBytes * 100L / chunkSize); - if (freePercentage == 0) { - return 99; - } - return 100 - freePercentage; - } - - long allocate(int normCapacity) { - if ((normCapacity & subpageOverflowMask) != 0) { // >= pageSize - return allocateRun(normCapacity); - } else { - return allocateSubpage(normCapacity); - } - } - - /** - * Update method used by allocate - * This is triggered only when a successor is allocated and all its predecessors - * need to update their state - * The minimal depth at which subtree rooted at id has some free space - * - * @param id id - */ - private void updateParentsAlloc(int id) { - while (id > 1) { - int parentId = id >>> 1; - byte val1 = value(id); - byte val2 = value(id ^ 1); - byte val = val1 < val2 ? val1 : val2; - setValue(parentId, val); - id = parentId; - } - } - - /** - * Update method used by free - * This needs to handle the special case when both children are completely free - * in which case parent be directly allocated on request of size = child-size * 2 - * - * @param id id - */ - private void updateParentsFree(int id) { - int logChild = depth(id) + 1; - while (id > 1) { - int parentId = id >>> 1; - byte val1 = value(id); - byte val2 = value(id ^ 1); - logChild -= 1; // in first iteration equals log, subsequently reduce 1 from logChild as we traverse up - - if (val1 == logChild && val2 == logChild) { - setValue(parentId, (byte) (logChild - 1)); - } else { - byte val = val1 < val2 ? val1 : val2; - setValue(parentId, val); - } - - id = parentId; - } - } - - /** - * Algorithm to allocate an index in memoryMap when we query for a free node - * at depth d - * - * @param d depth - * @return index in memoryMap - */ - private int allocateNode(int d) { - int id = 1; - int initial = - (1 << d); // has last d bits = 0 and rest all = 1 - byte val = value(id); - if (val > d) { // unusable - return -1; - } - while (val < d || (id & initial) == 0) { // id & initial == 1 << d for all ids at depth d, for < d it is 0 - id <<= 1; - val = value(id); - if (val > d) { - id ^= 1; - val = value(id); - } - } - byte value = value(id); - assert value == d && (id & initial) == 1 << d : String.format("val = %d, id & initial = %d, d = %d", - value, id & initial, d); - setValue(id, unusable); // mark as unusable - updateParentsAlloc(id); - return id; - } - - /** - * Allocate a run of pages (>=1) - * - * @param normCapacity normalized capacity - * @return index in memoryMap - */ - private long allocateRun(int normCapacity) { - int d = maxOrder - (log2(normCapacity) - pageShifts); - int id = allocateNode(d); - if (id < 0) { - return id; - } - freeBytes -= runLength(id); - return id; - } - - /** - * Create/ initialize a new PoolSubpage of normCapacity - * Any PoolSubpage created/ initialized here is added to subpage pool in the PoolArena that owns this PoolChunk - * - * @param normCapacity normalized capacity - * @return index in memoryMap - */ - private long allocateSubpage(int normCapacity) { - int d = maxOrder; // subpages are only be allocated from pages i.e., leaves - int id = allocateNode(d); - if (id < 0) { - return id; - } - - final PoolSubpage[] subpages = this.subpages; - final int pageSize = this.pageSize; - - freeBytes -= pageSize; - - int subpageIdx = subpageIdx(id); - PoolSubpage subpage = subpages[subpageIdx]; - if (subpage == null) { - subpage = new PoolSubpage(this, id, runOffset(id), pageSize, normCapacity); - subpages[subpageIdx] = subpage; - } else { - subpage.init(normCapacity); - } - return subpage.allocate(); - } - - /** - * Free a subpage or a run of pages - * When a subpage is freed from PoolSubpage, it might be added back to subpage pool of the owning PoolArena - * If the subpage pool in PoolArena has at least one other PoolSubpage of given elemSize, we can - * completely free the owning Page so it is available for subsequent allocations - * - * @param handle handle to free - */ - void free(long handle) { - int memoryMapIdx = (int) handle; - int bitmapIdx = (int) (handle >>> Integer.SIZE); - - if (bitmapIdx != 0) { // free a subpage - PoolSubpage subpage = subpages[subpageIdx(memoryMapIdx)]; - assert subpage != null && subpage.doNotDestroy; - if (subpage.free(bitmapIdx & 0x3FFFFFFF)) { - return; - } - } - freeBytes += runLength(memoryMapIdx); - setValue(memoryMapIdx, depth(memoryMapIdx)); - updateParentsFree(memoryMapIdx); - } - - void initBuf(PooledByteBuf buf, long handle, int reqCapacity) { - int memoryMapIdx = (int) handle; - int bitmapIdx = (int) (handle >>> Integer.SIZE); - if (bitmapIdx == 0) { - byte val = value(memoryMapIdx); - assert val == unusable : String.valueOf(val); - buf.init(this, handle, runOffset(memoryMapIdx), reqCapacity, runLength(memoryMapIdx)); - } else { - initBufWithSubpage(buf, handle, bitmapIdx, reqCapacity); - } - } - - void initBufWithSubpage(PooledByteBuf buf, long handle, int reqCapacity) { - initBufWithSubpage(buf, handle, (int) (handle >>> Integer.SIZE), reqCapacity); - } - - private void initBufWithSubpage(PooledByteBuf buf, long handle, int bitmapIdx, int reqCapacity) { - assert bitmapIdx != 0; - - int memoryMapIdx = (int) handle; - - PoolSubpage subpage = subpages[subpageIdx(memoryMapIdx)]; - assert subpage.doNotDestroy; - assert reqCapacity <= subpage.elemSize; - - buf.init( - this, handle, - runOffset(memoryMapIdx) + (bitmapIdx & 0x3FFFFFFF) * subpage.elemSize, reqCapacity, subpage.elemSize); - } - - private byte value(int id) { - return memoryMap[id]; - } - - private void setValue(int id, byte val) { - memoryMap[id] = val; - } - - private byte depth(int id) { - return depthMap[id]; - } - - private static int log2(int val) { - // compute the (0-based, with lsb = 0) position of highest set bit i.e, log2 - return Integer.SIZE - 1 - Integer.numberOfLeadingZeros(val); - } - - private int runLength(int id) { - // represents the size in #bytes supported by node 'id' in the tree - return 1 << log2ChunkSize - depth(id); - } - - private int runOffset(int id) { - // represents the 0-based offset in #bytes from start of the byte-array chunk - int shift = id ^ 1 << depth(id); - return shift * runLength(id); - } - - private int subpageIdx(int memoryMapIdx) { - return memoryMapIdx ^ maxSubpageAllocs; // remove highest set bit, to get offset - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("Chunk("); - buf.append(Integer.toHexString(System.identityHashCode(this))); - buf.append(": "); - buf.append(usage()); - buf.append("%, "); - buf.append(chunkSize - freeBytes); - buf.append('/'); - buf.append(chunkSize); - buf.append(')'); - return buf.toString(); - } -} diff --git a/java/src/game/net/buffer/PoolChunkList.java b/java/src/game/net/buffer/PoolChunkList.java deleted file mode 100644 index 0f980e3..0000000 --- a/java/src/game/net/buffer/PoolChunkList.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import game.net.util.internal.StringUtil; - -final class PoolChunkList { - private final PoolArena arena; - private final PoolChunkList nextList; - PoolChunkList prevList; - - private final int minUsage; - private final int maxUsage; - - private PoolChunk head; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - PoolChunkList(PoolArena arena, PoolChunkList nextList, int minUsage, int maxUsage) { - this.arena = arena; - this.nextList = nextList; - this.minUsage = minUsage; - this.maxUsage = maxUsage; - } - - boolean allocate(PooledByteBuf buf, int reqCapacity, int normCapacity) { - if (head == null) { - return false; - } - - for (PoolChunk cur = head;;) { - long handle = cur.allocate(normCapacity); - if (handle < 0) { - cur = cur.next; - if (cur == null) { - return false; - } - } else { - cur.initBuf(buf, handle, reqCapacity); - if (cur.usage() >= maxUsage) { - remove(cur); - nextList.add(cur); - } - return true; - } - } - } - - void free(PoolChunk chunk, long handle) { - chunk.free(handle); - if (chunk.usage() < minUsage) { - remove(chunk); - if (prevList == null) { - assert chunk.usage() == 0; - arena.destroyChunk(chunk); - } else { - prevList.add(chunk); - } - } - } - - void add(PoolChunk chunk) { - if (chunk.usage() >= maxUsage) { - nextList.add(chunk); - return; - } - - chunk.parent = this; - if (head == null) { - head = chunk; - chunk.prev = null; - chunk.next = null; - } else { - chunk.prev = null; - chunk.next = head; - head.prev = chunk; - head = chunk; - } - } - - private void remove(PoolChunk cur) { - if (cur == head) { - head = cur.next; - if (head != null) { - head.prev = null; - } - } else { - PoolChunk next = cur.next; - cur.prev.next = next; - if (next != null) { - next.prev = cur.prev; - } - } - } - - @Override - public String toString() { - if (head == null) { - return "none"; - } - - StringBuilder buf = new StringBuilder(); - for (PoolChunk cur = head;;) { - buf.append(cur); - cur = cur.next; - if (cur == null) { - break; - } - buf.append(StringUtil.NEWLINE); - } - - return buf.toString(); - } -} diff --git a/java/src/game/net/buffer/PoolSubpage.java b/java/src/game/net/buffer/PoolSubpage.java deleted file mode 100644 index c2130fc..0000000 --- a/java/src/game/net/buffer/PoolSubpage.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -final class PoolSubpage { - - final PoolChunk chunk; - private final int memoryMapIdx; - private final int runOffset; - private final int pageSize; - private final long[] bitmap; - - PoolSubpage prev; - PoolSubpage next; - - boolean doNotDestroy; - int elemSize; - private int maxNumElems; - private int bitmapLength; - private int nextAvail; - private int numAvail; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - /** Special constructor that creates a linked list head */ - PoolSubpage(int pageSize) { - chunk = null; - memoryMapIdx = -1; - runOffset = -1; - elemSize = -1; - this.pageSize = pageSize; - bitmap = null; - } - - PoolSubpage(PoolChunk chunk, int memoryMapIdx, int runOffset, int pageSize, int elemSize) { - this.chunk = chunk; - this.memoryMapIdx = memoryMapIdx; - this.runOffset = runOffset; - this.pageSize = pageSize; - bitmap = new long[pageSize >>> 10]; // pageSize / 16 / 64 - init(elemSize); - } - - void init(int elemSize) { - doNotDestroy = true; - this.elemSize = elemSize; - if (elemSize != 0) { - maxNumElems = numAvail = pageSize / elemSize; - nextAvail = 0; - bitmapLength = maxNumElems >>> 6; - if ((maxNumElems & 63) != 0) { - bitmapLength ++; - } - - for (int i = 0; i < bitmapLength; i ++) { - bitmap[i] = 0; - } - } - - addToPool(); - } - - /** - * Returns the bitmap index of the subpage allocation. - */ - long allocate() { - if (elemSize == 0) { - return toHandle(0); - } - - if (numAvail == 0 || !doNotDestroy) { - return -1; - } - - final int bitmapIdx = getNextAvail(); - int q = bitmapIdx >>> 6; - int r = bitmapIdx & 63; - assert (bitmap[q] >>> r & 1) == 0; - bitmap[q] |= 1L << r; - - if (-- numAvail == 0) { - removeFromPool(); - } - - return toHandle(bitmapIdx); - } - - /** - * @return {@code true} if this subpage is in use. - * {@code false} if this subpage is not used by its chunk and thus it's OK to be released. - */ - boolean free(int bitmapIdx) { - - if (elemSize == 0) { - return true; - } - - int q = bitmapIdx >>> 6; - int r = bitmapIdx & 63; - assert (bitmap[q] >>> r & 1) != 0; - bitmap[q] ^= 1L << r; - - setNextAvail(bitmapIdx); - - if (numAvail ++ == 0) { - addToPool(); - return true; - } - - if (numAvail != maxNumElems) { - return true; - } else { - // Subpage not in use (numAvail == maxNumElems) - if (prev == next) { - // Do not remove if this subpage is the only one left in the pool. - return true; - } - - // Remove this subpage from the pool if there are other subpages left in the pool. - doNotDestroy = false; - removeFromPool(); - return false; - } - } - - private void addToPool() { - PoolSubpage head = chunk.arena.findSubpagePoolHead(elemSize); - assert prev == null && next == null; - prev = head; - next = head.next; - next.prev = this; - head.next = this; - } - - private void removeFromPool() { - assert prev != null && next != null; - prev.next = next; - next.prev = prev; - next = null; - prev = null; - } - - private void setNextAvail(int bitmapIdx) { - nextAvail = bitmapIdx; - } - - private int getNextAvail() { - int nextAvail = this.nextAvail; - if (nextAvail >= 0) { - this.nextAvail = -1; - return nextAvail; - } - return findNextAvail(); - } - - private int findNextAvail() { - final long[] bitmap = this.bitmap; - final int bitmapLength = this.bitmapLength; - for (int i = 0; i < bitmapLength; i ++) { - long bits = bitmap[i]; - if (~bits != 0) { - return findNextAvail0(i, bits); - } - } - return -1; - } - - private int findNextAvail0(int i, long bits) { - final int maxNumElems = this.maxNumElems; - final int baseVal = i << 6; - - for (int j = 0; j < 64; j ++) { - if ((bits & 1) == 0) { - int val = baseVal | j; - if (val < maxNumElems) { - return val; - } else { - break; - } - } - bits >>>= 1; - } - return -1; - } - - private long toHandle(int bitmapIdx) { - return 0x4000000000000000L | (long) bitmapIdx << 32 | memoryMapIdx; - } - - public String toString() { - if (!doNotDestroy) { - return "(" + memoryMapIdx + ": not in use)"; - } - - return String.valueOf('(') + memoryMapIdx + ": " + (maxNumElems - numAvail) + '/' + maxNumElems + - ", offset: " + runOffset + ", length: " + pageSize + ", elemSize: " + elemSize + ')'; - } -} diff --git a/java/src/game/net/buffer/PoolThreadCache.java b/java/src/game/net/buffer/PoolThreadCache.java deleted file mode 100644 index fa12a77..0000000 --- a/java/src/game/net/buffer/PoolThreadCache.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - - -import java.nio.ByteBuffer; - -import game.net.util.ThreadDeathWatcher; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Acts a Thread cache for allocations. This implementation is moduled after - * jemalloc and the descripted - * technics of Scalable memory allocation using jemalloc. - */ -final class PoolThreadCache { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PoolThreadCache.class); - - final PoolArena heapArena; - final PoolArena directArena; - - // Hold the caches for the different size classes, which are tiny, small and normal. - private final MemoryRegionCache[] tinySubPageHeapCaches; - private final MemoryRegionCache[] smallSubPageHeapCaches; - private final MemoryRegionCache[] tinySubPageDirectCaches; - private final MemoryRegionCache[] smallSubPageDirectCaches; - private final MemoryRegionCache[] normalHeapCaches; - private final MemoryRegionCache[] normalDirectCaches; - - // Used for bitshifting when calculate the index of normal caches later - private final int numShiftsNormalDirect; - private final int numShiftsNormalHeap; - private final int freeSweepAllocationThreshold; - - private int allocations; - - private final Thread thread = Thread.currentThread(); - private final Runnable freeTask = new Runnable() { - @Override - public void run() { - free0(); - } - }; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - PoolThreadCache(PoolArena heapArena, PoolArena directArena, - int tinyCacheSize, int smallCacheSize, int normalCacheSize, - int maxCachedBufferCapacity, int freeSweepAllocationThreshold) { - if (maxCachedBufferCapacity < 0) { - throw new IllegalArgumentException("maxCachedBufferCapacity: " - + maxCachedBufferCapacity + " (expected: >= 0)"); - } - if (freeSweepAllocationThreshold < 1) { - throw new IllegalArgumentException("freeSweepAllocationThreshold: " - + maxCachedBufferCapacity + " (expected: > 0)"); - } - this.freeSweepAllocationThreshold = freeSweepAllocationThreshold; - this.heapArena = heapArena; - this.directArena = directArena; - if (directArena != null) { - tinySubPageDirectCaches = createSubPageCaches(tinyCacheSize, PoolArena.numTinySubpagePools); - smallSubPageDirectCaches = createSubPageCaches(smallCacheSize, directArena.numSmallSubpagePools); - - numShiftsNormalDirect = log2(directArena.pageSize); - normalDirectCaches = createNormalCaches( - normalCacheSize, maxCachedBufferCapacity, directArena); - } else { - // No directArea is configured so just null out all caches - tinySubPageDirectCaches = null; - smallSubPageDirectCaches = null; - normalDirectCaches = null; - numShiftsNormalDirect = -1; - } - if (heapArena != null) { - // Create the caches for the heap allocations - tinySubPageHeapCaches = createSubPageCaches(tinyCacheSize, PoolArena.numTinySubpagePools); - smallSubPageHeapCaches = createSubPageCaches(smallCacheSize, heapArena.numSmallSubpagePools); - - numShiftsNormalHeap = log2(heapArena.pageSize); - normalHeapCaches = createNormalCaches( - normalCacheSize, maxCachedBufferCapacity, heapArena); - } else { - // No heapArea is configured so just null out all caches - tinySubPageHeapCaches = null; - smallSubPageHeapCaches = null; - normalHeapCaches = null; - numShiftsNormalHeap = -1; - } - - // The thread-local cache will keep a list of pooled buffers which must be returned to - // the pool when the thread is not alive anymore. - ThreadDeathWatcher.watch(thread, freeTask); - } - - private static SubPageMemoryRegionCache[] createSubPageCaches(int cacheSize, int numCaches) { - if (cacheSize > 0) { - - SubPageMemoryRegionCache[] cache = new SubPageMemoryRegionCache[numCaches]; - for (int i = 0; i < cache.length; i++) { - // TODO: maybe use cacheSize / cache.length - cache[i] = new SubPageMemoryRegionCache(cacheSize); - } - return cache; - } else { - return null; - } - } - - private static NormalMemoryRegionCache[] createNormalCaches( - int cacheSize, int maxCachedBufferCapacity, PoolArena area) { - if (cacheSize > 0) { - int max = Math.min(area.chunkSize, maxCachedBufferCapacity); - int arraySize = Math.max(1, max / area.pageSize); - - - NormalMemoryRegionCache[] cache = new NormalMemoryRegionCache[arraySize]; - for (int i = 0; i < cache.length; i++) { - cache[i] = new NormalMemoryRegionCache(cacheSize); - } - return cache; - } else { - return null; - } - } - - private static int log2(int val) { - int res = 0; - while (val > 1) { - val >>= 1; - res++; - } - return res; - } - - /** - * Try to allocate a tiny buffer out of the cache. Returns {@code true} if successful {@code false} otherwise - */ - boolean allocateTiny(PoolArena area, PooledByteBuf buf, int reqCapacity, int normCapacity) { - return allocate(cacheForTiny(area, normCapacity), buf, reqCapacity); - } - - /** - * Try to allocate a small buffer out of the cache. Returns {@code true} if successful {@code false} otherwise - */ - boolean allocateSmall(PoolArena area, PooledByteBuf buf, int reqCapacity, int normCapacity) { - return allocate(cacheForSmall(area, normCapacity), buf, reqCapacity); - } - - /** - * Try to allocate a small buffer out of the cache. Returns {@code true} if successful {@code false} otherwise - */ - boolean allocateNormal(PoolArena area, PooledByteBuf buf, int reqCapacity, int normCapacity) { - return allocate(cacheForNormal(area, normCapacity), buf, reqCapacity); - } - - - private boolean allocate(MemoryRegionCache cache, PooledByteBuf buf, int reqCapacity) { - if (cache == null) { - // no cache found so just return false here - return false; - } - boolean allocated = cache.allocate(buf, reqCapacity); - if (++ allocations >= freeSweepAllocationThreshold) { - allocations = 0; - trim(); - } - return allocated; - } - - /** - * Add {@link PoolChunk} and {@code handle} to the cache if there is enough room. - * Returns {@code true} if it fit into the cache {@code false} otherwise. - */ - - boolean add(PoolArena area, PoolChunk chunk, long handle, int normCapacity) { - MemoryRegionCache cache; - if (area.isTinyOrSmall(normCapacity)) { - if (PoolArena.isTiny(normCapacity)) { - cache = cacheForTiny(area, normCapacity); - } else { - cache = cacheForSmall(area, normCapacity); - } - } else { - cache = cacheForNormal(area, normCapacity); - } - if (cache == null) { - return false; - } - return cache.add(chunk, handle); - } - - /** - * Should be called if the Thread that uses this cache is about to exist to release resources out of the cache - */ - void free() { - ThreadDeathWatcher.unwatch(thread, freeTask); - free0(); - } - - private void free0() { - int numFreed = free(tinySubPageDirectCaches) + - free(smallSubPageDirectCaches) + - free(normalDirectCaches) + - free(tinySubPageHeapCaches) + - free(smallSubPageHeapCaches) + - free(normalHeapCaches); - - if (numFreed > 0 && logger.isDebugEnabled()) { - logger.debug("Freed {} thread-local buffer(s) from thread: {}", numFreed, thread.getName()); - } - } - - private static int free(MemoryRegionCache[] caches) { - if (caches == null) { - return 0; - } - - int numFreed = 0; - for (MemoryRegionCache c: caches) { - numFreed += free(c); - } - return numFreed; - } - - private static int free(MemoryRegionCache cache) { - if (cache == null) { - return 0; - } - return cache.free(); - } - - void trim() { - trim(tinySubPageDirectCaches); - trim(smallSubPageDirectCaches); - trim(normalDirectCaches); - trim(tinySubPageHeapCaches); - trim(smallSubPageHeapCaches); - trim(normalHeapCaches); - } - - private static void trim(MemoryRegionCache[] caches) { - if (caches == null) { - return; - } - for (MemoryRegionCache c: caches) { - trim(c); - } - } - - private static void trim(MemoryRegionCache cache) { - if (cache == null) { - return; - } - cache.trim(); - } - - private MemoryRegionCache cacheForTiny(PoolArena area, int normCapacity) { - int idx = PoolArena.tinyIdx(normCapacity); - if (area.isDirect()) { - return cache(tinySubPageDirectCaches, idx); - } - return cache(tinySubPageHeapCaches, idx); - } - - private MemoryRegionCache cacheForSmall(PoolArena area, int normCapacity) { - int idx = PoolArena.smallIdx(normCapacity); - if (area.isDirect()) { - return cache(smallSubPageDirectCaches, idx); - } - return cache(smallSubPageHeapCaches, idx); - } - - private MemoryRegionCache cacheForNormal(PoolArena area, int normCapacity) { - if (area.isDirect()) { - int idx = log2(normCapacity >> numShiftsNormalDirect); - return cache(normalDirectCaches, idx); - } - int idx = log2(normCapacity >> numShiftsNormalHeap); - return cache(normalHeapCaches, idx); - } - - private static MemoryRegionCache cache(MemoryRegionCache[] cache, int idx) { - if (cache == null || idx > cache.length - 1) { - return null; - } - return cache[idx]; - } - - /** - * Cache used for buffers which are backed by TINY or SMALL size. - */ - private static final class SubPageMemoryRegionCache extends MemoryRegionCache { - SubPageMemoryRegionCache(int size) { - super(size); - } - - @Override - protected void initBuf( - PoolChunk chunk, long handle, PooledByteBuf buf, int reqCapacity) { - chunk.initBufWithSubpage(buf, handle, reqCapacity); - } - } - - /** - * Cache used for buffers which are backed by NORMAL size. - */ - private static final class NormalMemoryRegionCache extends MemoryRegionCache { - NormalMemoryRegionCache(int size) { - super(size); - } - - @Override - protected void initBuf( - PoolChunk chunk, long handle, PooledByteBuf buf, int reqCapacity) { - chunk.initBuf(buf, handle, reqCapacity); - } - } - - /** - * Cache of {@link PoolChunk} and handles which can be used to allocate a buffer without locking at all. - */ - private abstract static class MemoryRegionCache { - private final Entry[] entries; - private final int maxUnusedCached; - private int head; - private int tail; - private int maxEntriesInUse; - private int entriesInUse; - - - MemoryRegionCache(int size) { - entries = new Entry[powerOfTwo(size)]; - for (int i = 0; i < entries.length; i++) { - entries[i] = new Entry(); - } - maxUnusedCached = size / 2; - } - - private static int powerOfTwo(int res) { - if (res <= 2) { - return 2; - } - res--; - res |= res >> 1; - res |= res >> 2; - res |= res >> 4; - res |= res >> 8; - res |= res >> 16; - res++; - return res; - } - - /** - * Init the {@link PooledByteBuf} using the provided chunk and handle with the capacity restrictions. - */ - protected abstract void initBuf(PoolChunk chunk, long handle, - PooledByteBuf buf, int reqCapacity); - - /** - * Add to cache if not already full. - */ - public boolean add(PoolChunk chunk, long handle) { - Entry entry = entries[tail]; - if (entry.chunk != null) { - // cache is full - return false; - } - entriesInUse --; - - entry.chunk = chunk; - entry.handle = handle; - tail = nextIdx(tail); - return true; - } - - /** - * Allocate something out of the cache if possible and remove the entry from the cache. - */ - public boolean allocate(PooledByteBuf buf, int reqCapacity) { - Entry entry = entries[head]; - if (entry.chunk == null) { - return false; - } - - entriesInUse ++; - if (maxEntriesInUse < entriesInUse) { - maxEntriesInUse = entriesInUse; - } - initBuf(entry.chunk, entry.handle, buf, reqCapacity); - // only null out the chunk as we only use the chunk to check if the buffer is full or not. - entry.chunk = null; - head = nextIdx(head); - return true; - } - - /** - * Clear out this cache and free up all previous cached {@link PoolChunk}s and {@code handle}s. - */ - public int free() { - int numFreed = 0; - entriesInUse = 0; - maxEntriesInUse = 0; - for (int i = head;; i = nextIdx(i)) { - if (freeEntry(entries[i])) { - numFreed++; - } else { - // all cleared - return numFreed; - } - } - } - - /** - * Free up cached {@link PoolChunk}s if not allocated frequently enough. - */ - private void trim() { - int free = size() - maxEntriesInUse; - entriesInUse = 0; - maxEntriesInUse = 0; - - if (free <= maxUnusedCached) { - return; - } - - int i = head; - for (; free > 0; free--) { - if (!freeEntry(entries[i])) { - // all freed - return; - } - i = nextIdx(i); - } - } - - - private static boolean freeEntry(Entry entry) { - PoolChunk chunk = entry.chunk; - if (chunk == null) { - return false; - } - // need to synchronize on the area from which it was allocated before. - synchronized (chunk.arena) { - chunk.parent.free(chunk, entry.handle); - } - entry.chunk = null; - return true; - } - - /** - * Return the number of cached entries. - */ - private int size() { - return tail - head & entries.length - 1; - } - - private int nextIdx(int index) { - // use bitwise operation as this is faster as using modulo. - return index + 1 & entries.length - 1; - } - - private static final class Entry { - PoolChunk chunk; - long handle; - } - } -} diff --git a/java/src/game/net/buffer/PooledByteBuf.java b/java/src/game/net/buffer/PooledByteBuf.java deleted file mode 100644 index b36db4b..0000000 --- a/java/src/game/net/buffer/PooledByteBuf.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import game.net.util.Recycler; - -abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { - - private final Recycler.Handle recyclerHandle; - - protected PoolChunk chunk; - protected long handle; - protected T memory; - protected int offset; - protected int length; - int maxLength; - - private ByteBuffer tmpNioBuf; - - protected PooledByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(maxCapacity); - this.recyclerHandle = recyclerHandle; - } - - void init(PoolChunk chunk, long handle, int offset, int length, int maxLength) { - assert handle >= 0; - assert chunk != null; - - this.chunk = chunk; - this.handle = handle; - memory = chunk.memory; - this.offset = offset; - this.length = length; - this.maxLength = maxLength; - setIndex(0, 0); - tmpNioBuf = null; - } - - void initUnpooled(PoolChunk chunk, int length) { - assert chunk != null; - - this.chunk = chunk; - handle = 0; - memory = chunk.memory; - offset = 0; - this.length = maxLength = length; - setIndex(0, 0); - tmpNioBuf = null; - } - - @Override - public final int capacity() { - return length; - } - - @Override - public final ByteBuf capacity(int newCapacity) { - ensureAccessible(); - - // If the request capacity does not require reallocation, just update the length of the memory. - if (chunk.unpooled) { - if (newCapacity == length) { - return this; - } - } else { - if (newCapacity > length) { - if (newCapacity <= maxLength) { - length = newCapacity; - return this; - } - } else if (newCapacity < length) { - if (newCapacity > maxLength >>> 1) { - if (maxLength <= 512) { - if (newCapacity > maxLength - 16) { - length = newCapacity; - setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity)); - return this; - } - } else { // > 512 (i.e. >= 1024) - length = newCapacity; - setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity)); - return this; - } - } - } else { - return this; - } - } - - // Reallocation required. - chunk.arena.reallocate(this, newCapacity, true); - return this; - } - - @Override - public final ByteBufAllocator alloc() { - return chunk.arena.parent; - } - - @Override - public final ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public final ByteBuf unwrap() { - return null; - } - - protected final ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = newInternalNioBuffer(memory); - } - return tmpNioBuf; - } - - protected abstract ByteBuffer newInternalNioBuffer(T memory); - - @Override - protected final void deallocate() { - if (handle >= 0) { - final long handle = this.handle; - this.handle = -1; - memory = null; - chunk.arena.free(chunk, handle, maxLength); - recycle(); - } - } - - private void recycle() { - Recycler.Handle recyclerHandle = this.recyclerHandle; - if (recyclerHandle != null) { - ((Recycler) recycler()).recycle(this, recyclerHandle); - } - } - - protected abstract Recycler recycler(); - - protected final int idx(int index) { - return offset + index; - } -} diff --git a/java/src/game/net/buffer/PooledByteBufAllocator.java b/java/src/game/net/buffer/PooledByteBufAllocator.java deleted file mode 100644 index 6416f42..0000000 --- a/java/src/game/net/buffer/PooledByteBufAllocator.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.nio.ByteBuffer; -import java.util.concurrent.atomic.AtomicInteger; - -import game.net.util.concurrent.FastThreadLocal; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.SystemPropertyUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -public class PooledByteBufAllocator extends AbstractByteBufAllocator { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PooledByteBufAllocator.class); - private static final int DEFAULT_NUM_HEAP_ARENA; - private static final int DEFAULT_NUM_DIRECT_ARENA; - - private static final int DEFAULT_PAGE_SIZE; - private static final int DEFAULT_MAX_ORDER; // 8192 << 11 = 16 MiB per chunk - private static final int DEFAULT_TINY_CACHE_SIZE; - private static final int DEFAULT_SMALL_CACHE_SIZE; - private static final int DEFAULT_NORMAL_CACHE_SIZE; - private static final int DEFAULT_MAX_CACHED_BUFFER_CAPACITY; - private static final int DEFAULT_CACHE_TRIM_INTERVAL; - - private static final int MIN_PAGE_SIZE = 4096; - private static final int MAX_CHUNK_SIZE = (int) (((long) Integer.MAX_VALUE + 1) / 2); - - static { - int defaultPageSize = SystemPropertyUtil.getInt("io.netty.allocator.pageSize", 8192); - Throwable pageSizeFallbackCause = null; - try { - validateAndCalculatePageShifts(defaultPageSize); - } catch (Throwable t) { - pageSizeFallbackCause = t; - defaultPageSize = 8192; - } - DEFAULT_PAGE_SIZE = defaultPageSize; - - int defaultMaxOrder = SystemPropertyUtil.getInt("io.netty.allocator.maxOrder", 11); - Throwable maxOrderFallbackCause = null; - try { - validateAndCalculateChunkSize(DEFAULT_PAGE_SIZE, defaultMaxOrder); - } catch (Throwable t) { - maxOrderFallbackCause = t; - defaultMaxOrder = 11; - } - DEFAULT_MAX_ORDER = defaultMaxOrder; - - // Determine reasonable default for nHeapArena and nDirectArena. - // Assuming each arena has 3 chunks, the pool should not consume more than 50% of max memory. - final Runtime runtime = Runtime.getRuntime(); - final int defaultChunkSize = DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER; - DEFAULT_NUM_HEAP_ARENA = Math.max(0, - SystemPropertyUtil.getInt( - "io.netty.allocator.numHeapArenas", - (int) Math.min( - runtime.availableProcessors(), - Runtime.getRuntime().maxMemory() / defaultChunkSize / 2 / 3))); - DEFAULT_NUM_DIRECT_ARENA = Math.max(0, - SystemPropertyUtil.getInt( - "io.netty.allocator.numDirectArenas", - (int) Math.min( - runtime.availableProcessors(), - PlatformDependent.maxDirectMemory() / defaultChunkSize / 2 / 3))); - - // cache sizes - DEFAULT_TINY_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.tinyCacheSize", 512); - DEFAULT_SMALL_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.smallCacheSize", 256); - DEFAULT_NORMAL_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.normalCacheSize", 64); - - // 32 kb is the default maximum capacity of the cached buffer. Similar to what is explained in - // 'Scalable memory allocation using jemalloc' - DEFAULT_MAX_CACHED_BUFFER_CAPACITY = SystemPropertyUtil.getInt( - "io.netty.allocator.maxCachedBufferCapacity", 32 * 1024); - - // the number of threshold of allocations when cached entries will be freed up if not frequently used - DEFAULT_CACHE_TRIM_INTERVAL = SystemPropertyUtil.getInt( - "io.netty.allocator.cacheTrimInterval", 8192); - - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.allocator.numHeapArenas: {}", DEFAULT_NUM_HEAP_ARENA); - logger.debug("-Dio.netty.allocator.numDirectArenas: {}", DEFAULT_NUM_DIRECT_ARENA); - if (pageSizeFallbackCause == null) { - logger.debug("-Dio.netty.allocator.pageSize: {}", DEFAULT_PAGE_SIZE); - } else { - logger.debug("-Dio.netty.allocator.pageSize: {}", DEFAULT_PAGE_SIZE, pageSizeFallbackCause); - } - if (maxOrderFallbackCause == null) { - logger.debug("-Dio.netty.allocator.maxOrder: {}", DEFAULT_MAX_ORDER); - } else { - logger.debug("-Dio.netty.allocator.maxOrder: {}", DEFAULT_MAX_ORDER, maxOrderFallbackCause); - } - logger.debug("-Dio.netty.allocator.chunkSize: {}", DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER); - logger.debug("-Dio.netty.allocator.tinyCacheSize: {}", DEFAULT_TINY_CACHE_SIZE); - logger.debug("-Dio.netty.allocator.smallCacheSize: {}", DEFAULT_SMALL_CACHE_SIZE); - logger.debug("-Dio.netty.allocator.normalCacheSize: {}", DEFAULT_NORMAL_CACHE_SIZE); - logger.debug("-Dio.netty.allocator.maxCachedBufferCapacity: {}", DEFAULT_MAX_CACHED_BUFFER_CAPACITY); - logger.debug("-Dio.netty.allocator.cacheTrimInterval: {}", DEFAULT_CACHE_TRIM_INTERVAL); - } - } - - public static final PooledByteBufAllocator DEFAULT = - new PooledByteBufAllocator(PlatformDependent.directBufferPreferred()); - - private final PoolArena[] heapArenas; - private final PoolArena[] directArenas; - private final int tinyCacheSize; - private final int smallCacheSize; - private final int normalCacheSize; - - final PoolThreadLocalCache threadCache; - - public PooledByteBufAllocator() { - this(false); - } - - public PooledByteBufAllocator(boolean preferDirect) { - this(preferDirect, DEFAULT_NUM_HEAP_ARENA, DEFAULT_NUM_DIRECT_ARENA, DEFAULT_PAGE_SIZE, DEFAULT_MAX_ORDER); - } - - public PooledByteBufAllocator(int nHeapArena, int nDirectArena, int pageSize, int maxOrder) { - this(false, nHeapArena, nDirectArena, pageSize, maxOrder); - } - - public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder) { - this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder, - DEFAULT_TINY_CACHE_SIZE, DEFAULT_SMALL_CACHE_SIZE, DEFAULT_NORMAL_CACHE_SIZE); - } - - public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder, - int tinyCacheSize, int smallCacheSize, int normalCacheSize) { - super(preferDirect); - threadCache = new PoolThreadLocalCache(); - this.tinyCacheSize = tinyCacheSize; - this.smallCacheSize = smallCacheSize; - this.normalCacheSize = normalCacheSize; - final int chunkSize = validateAndCalculateChunkSize(pageSize, maxOrder); - - if (nHeapArena < 0) { - throw new IllegalArgumentException("nHeapArena: " + nHeapArena + " (expected: >= 0)"); - } - if (nDirectArena < 0) { - throw new IllegalArgumentException("nDirectArea: " + nDirectArena + " (expected: >= 0)"); - } - - int pageShifts = validateAndCalculatePageShifts(pageSize); - - if (nHeapArena > 0) { - heapArenas = newArenaArray(nHeapArena); - for (int i = 0; i < heapArenas.length; i ++) { - heapArenas[i] = new PoolArena.HeapArena(this, pageSize, maxOrder, pageShifts, chunkSize); - } - } else { - heapArenas = null; - } - - if (nDirectArena > 0) { - directArenas = newArenaArray(nDirectArena); - for (int i = 0; i < directArenas.length; i ++) { - directArenas[i] = new PoolArena.DirectArena(this, pageSize, maxOrder, pageShifts, chunkSize); - } - } else { - directArenas = null; - } - } - - @Deprecated - - public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder, - int tinyCacheSize, int smallCacheSize, int normalCacheSize, - long cacheThreadAliveCheckInterval) { - this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder, - tinyCacheSize, smallCacheSize, normalCacheSize); - } - - - private static PoolArena[] newArenaArray(int size) { - return new PoolArena[size]; - } - - private static int validateAndCalculatePageShifts(int pageSize) { - if (pageSize < MIN_PAGE_SIZE) { - throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: " + MIN_PAGE_SIZE + "+)"); - } - - if ((pageSize & pageSize - 1) != 0) { - throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: power of 2)"); - } - - // Logarithm base 2. At this point we know that pageSize is a power of two. - return Integer.SIZE - 1 - Integer.numberOfLeadingZeros(pageSize); - } - - private static int validateAndCalculateChunkSize(int pageSize, int maxOrder) { - if (maxOrder > 14) { - throw new IllegalArgumentException("maxOrder: " + maxOrder + " (expected: 0-14)"); - } - - // Ensure the resulting chunkSize does not overflow. - int chunkSize = pageSize; - for (int i = maxOrder; i > 0; i --) { - if (chunkSize > MAX_CHUNK_SIZE / 2) { - throw new IllegalArgumentException(String.format( - "pageSize (%d) << maxOrder (%d) must not exceed %d", pageSize, maxOrder, MAX_CHUNK_SIZE)); - } - chunkSize <<= 1; - } - return chunkSize; - } - - @Override - protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) { - PoolThreadCache cache = threadCache.get(); - PoolArena heapArena = cache.heapArena; - - ByteBuf buf; - if (heapArena != null) { - buf = heapArena.allocate(cache, initialCapacity, maxCapacity); - } else { - buf = new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity); - } - - return toLeakAwareBuffer(buf); - } - - @Override - protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) { - PoolThreadCache cache = threadCache.get(); - PoolArena directArena = cache.directArena; - - ByteBuf buf; - if (directArena != null) { - buf = directArena.allocate(cache, initialCapacity, maxCapacity); - } else { - if (PlatformDependent.hasUnsafe()) { - buf = new UnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity); - } else { - buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity); - } - } - - return toLeakAwareBuffer(buf); - } - - @Override - public boolean isDirectBufferPooled() { - return directArenas != null; - } - - /** - * Returns {@code true} if the calling {@link Thread} has a {@link ThreadLocal} cache for the allocated - * buffers. - */ - @Deprecated - public boolean hasThreadLocalCache() { - return threadCache.isSet(); - } - - /** - * Free all cached buffers for the calling {@link Thread}. - */ - @Deprecated - public void freeThreadLocalCache() { - threadCache.remove(); - } - - final class PoolThreadLocalCache extends FastThreadLocal { - private final AtomicInteger index = new AtomicInteger(); - - @Override - protected PoolThreadCache initialValue() { - final int idx = index.getAndIncrement(); - final PoolArena heapArena; - final PoolArena directArena; - - if (heapArenas != null) { - heapArena = heapArenas[Math.abs(idx % heapArenas.length)]; - } else { - heapArena = null; - } - - if (directArenas != null) { - directArena = directArenas[Math.abs(idx % directArenas.length)]; - } else { - directArena = null; - } - - return new PoolThreadCache( - heapArena, directArena, tinyCacheSize, smallCacheSize, normalCacheSize, - DEFAULT_MAX_CACHED_BUFFER_CAPACITY, DEFAULT_CACHE_TRIM_INTERVAL); - } - - @Override - protected void onRemoval(PoolThreadCache value) { - value.free(); - } - } - -// Too noisy at the moment. -// -// public String toString() { -// StringBuilder buf = new StringBuilder(); -// buf.append(heapArenas.length); -// buf.append(" heap arena(s):"); -// buf.append(StringUtil.NEWLINE); -// for (PoolArena a: heapArenas) { -// buf.append(a); -// } -// buf.append(directArenas.length); -// buf.append(" direct arena(s):"); -// buf.append(StringUtil.NEWLINE); -// for (PoolArena a: directArenas) { -// buf.append(a); -// } -// return buf.toString(); -// } -} diff --git a/java/src/game/net/buffer/PooledDirectByteBuf.java b/java/src/game/net/buffer/PooledDirectByteBuf.java deleted file mode 100644 index 3ed9e7d..0000000 --- a/java/src/game/net/buffer/PooledDirectByteBuf.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import game.net.util.Recycler; - -final class PooledDirectByteBuf extends PooledByteBuf { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PooledDirectByteBuf newObject(Handle handle) { - return new PooledDirectByteBuf(handle, 0); - } - }; - - static PooledDirectByteBuf newInstance(int maxCapacity) { - PooledDirectByteBuf buf = RECYCLER.get(); - buf.setRefCnt(1); - buf.maxCapacity(maxCapacity); - return buf; - } - - private PooledDirectByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(recyclerHandle, maxCapacity); - } - - @Override - protected ByteBuffer newInternalNioBuffer(ByteBuffer memory) { - return memory.duplicate(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - protected byte _getByte(int index) { - return memory.get(idx(index)); - } - - @Override - protected short _getShort(int index) { - return memory.getShort(idx(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - index = idx(index); - return (memory.get(index) & 0xff) << 16 | (memory.get(index + 1) & 0xff) << 8 | memory.get(index + 2) & 0xff; - } - - @Override - protected int _getInt(int index) { - return memory.getInt(idx(index)); - } - - @Override - protected long _getLong(int index) { - return memory.getLong(idx(index)); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else if (dst.nioBufferCount() > 0) { - for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) { - int bbLen = bb.remaining(); - getBytes(index, bb); - index += bbLen; - } - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - getBytes(index, dst, dstIndex, length, false); - return this; - } - - private void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) { - checkDstIndex(index, length, dstIndex, dst.length); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.get(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - getBytes(index, dst, false); - return this; - } - - private void getBytes(int index, ByteBuffer dst, boolean internal) { - checkIndex(index); - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - getBytes(index, out, length, false); - return this; - } - - private void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException { - checkIndex(index, length); - if (length == 0) { - return; - } - - byte[] tmp = new byte[length]; - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - tmpBuf.clear().position(idx(index)); - tmpBuf.get(tmp); - out.write(tmp); - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - checkReadableBytes(length); - getBytes(readerIndex, out, length, true); - readerIndex += length; - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - checkIndex(index, length); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - protected void _setByte(int index, int value) { - memory.put(idx(index), (byte) value); - } - - @Override - protected void _setShort(int index, int value) { - memory.putShort(idx(index), (short) value); - } - - @Override - protected void _setMedium(int index, int value) { - index = idx(index); - memory.put(index, (byte) (value >>> 16)); - memory.put(index + 1, (byte) (value >>> 8)); - memory.put(index + 2, (byte) value); - } - - @Override - protected void _setInt(int index, int value) { - memory.putInt(idx(index), value); - } - - @Override - protected void _setLong(int index, long value) { - memory.putLong(idx(index), value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.hasArray()) { - setBytes(index, src.array(), src.arrayOffset() + srcIndex, length); - } else if (src.nioBufferCount() > 0) { - for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) { - int bbLen = bb.remaining(); - setBytes(index, bb); - index += bbLen; - } - } else { - src.getBytes(srcIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - ByteBuffer tmpBuf = internalNioBuffer(); - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.put(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - checkIndex(index, src.remaining()); - ByteBuffer tmpBuf = internalNioBuffer(); - if (src == tmpBuf) { - src = src.duplicate(); - } - - index = idx(index); - tmpBuf.clear().position(index).limit(index + src.remaining()); - tmpBuf.put(src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - byte[] tmp = new byte[length]; - int readBytes = in.read(tmp); - if (readBytes <= 0) { - return readBytes; - } - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(idx(index)); - tmpBuf.put(tmp, 0, readBytes); - return readBytes; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - ByteBuffer tmpBuf = internalNioBuffer(); - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().directBuffer(length, maxCapacity()); - copy.writeBytes(this, index, length); - return copy; - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return ((ByteBuffer) memory.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - protected Recycler recycler() { - return RECYCLER; - } -} diff --git a/java/src/game/net/buffer/PooledHeapByteBuf.java b/java/src/game/net/buffer/PooledHeapByteBuf.java deleted file mode 100644 index 57bc6b8..0000000 --- a/java/src/game/net/buffer/PooledHeapByteBuf.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file tothe License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import game.net.util.Recycler; -import game.net.util.internal.PlatformDependent; - -final class PooledHeapByteBuf extends PooledByteBuf { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PooledHeapByteBuf newObject(Handle handle) { - return new PooledHeapByteBuf(handle, 0); - } - }; - - static PooledHeapByteBuf newInstance(int maxCapacity) { - PooledHeapByteBuf buf = RECYCLER.get(); - buf.setRefCnt(1); - buf.maxCapacity(maxCapacity); - return buf; - } - - private PooledHeapByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(recyclerHandle, maxCapacity); - } - - @Override - public boolean isDirect() { - return false; - } - - @Override - protected byte _getByte(int index) { - return memory[idx(index)]; - } - - @Override - protected short _getShort(int index) { - index = idx(index); - return (short) (memory[index] << 8 | memory[index + 1] & 0xFF); - } - - @Override - protected int _getUnsignedMedium(int index) { - index = idx(index); - return (memory[index] & 0xff) << 16 | - (memory[index + 1] & 0xff) << 8 | - memory[index + 2] & 0xff; - } - - @Override - protected int _getInt(int index) { - index = idx(index); - return (memory[index] & 0xff) << 24 | - (memory[index + 1] & 0xff) << 16 | - (memory[index + 2] & 0xff) << 8 | - memory[index + 3] & 0xff; - } - - @Override - protected long _getLong(int index) { - index = idx(index); - return ((long) memory[index] & 0xff) << 56 | - ((long) memory[index + 1] & 0xff) << 48 | - ((long) memory[index + 2] & 0xff) << 40 | - ((long) memory[index + 3] & 0xff) << 32 | - ((long) memory[index + 4] & 0xff) << 24 | - ((long) memory[index + 5] & 0xff) << 16 | - ((long) memory[index + 6] & 0xff) << 8 | - (long) memory[index + 7] & 0xff; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(memory, idx(index), dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, memory, idx(index), length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - System.arraycopy(memory, idx(index), dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex(index); - dst.put(memory, idx(index), Math.min(capacity() - index, dst.remaining())); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - out.write(memory, idx(index), length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - checkIndex(index, length); - index = idx(index); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = ByteBuffer.wrap(memory); - } - return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length)); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - protected void _setByte(int index, int value) { - memory[idx(index)] = (byte) value; - } - - @Override - protected void _setShort(int index, int value) { - index = idx(index); - memory[index] = (byte) (value >>> 8); - memory[index + 1] = (byte) value; - } - - @Override - protected void _setMedium(int index, int value) { - index = idx(index); - memory[index] = (byte) (value >>> 16); - memory[index + 1] = (byte) (value >>> 8); - memory[index + 2] = (byte) value; - } - - @Override - protected void _setInt(int index, int value) { - index = idx(index); - memory[index] = (byte) (value >>> 24); - memory[index + 1] = (byte) (value >>> 16); - memory[index + 2] = (byte) (value >>> 8); - memory[index + 3] = (byte) value; - } - - @Override - protected void _setLong(int index, long value) { - index = idx(index); - memory[index] = (byte) (value >>> 56); - memory[index + 1] = (byte) (value >>> 48); - memory[index + 2] = (byte) (value >>> 40); - memory[index + 3] = (byte) (value >>> 32); - memory[index + 4] = (byte) (value >>> 24); - memory[index + 5] = (byte) (value >>> 16); - memory[index + 6] = (byte) (value >>> 8); - memory[index + 7] = (byte) value; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.hasMemoryAddress()) { - PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, memory, idx(index), length); - } else if (src.hasArray()) { - setBytes(index, src.array(), src.arrayOffset() + srcIndex, length); - } else { - src.getBytes(srcIndex, memory, idx(index), length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - System.arraycopy(src, srcIndex, memory, idx(index), length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - int length = src.remaining(); - checkIndex(index, length); - src.get(memory, idx(index), length); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - return in.read(memory, idx(index), length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - index = idx(index); - try { - return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().heapBuffer(length, maxCapacity()); - copy.writeBytes(memory, idx(index), length); - return copy; - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - ByteBuffer buf = ByteBuffer.wrap(memory, index, length); - return buf.slice(); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public boolean hasArray() { - return true; - } - - @Override - public byte[] array() { - return memory; - } - - @Override - public int arrayOffset() { - return offset; - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - protected ByteBuffer newInternalNioBuffer(byte[] memory) { - return ByteBuffer.wrap(memory); - } - - @Override - protected Recycler recycler() { - return RECYCLER; - } -} diff --git a/java/src/game/net/buffer/PooledUnsafeDirectByteBuf.java b/java/src/game/net/buffer/PooledUnsafeDirectByteBuf.java deleted file mode 100644 index b601913..0000000 --- a/java/src/game/net/buffer/PooledUnsafeDirectByteBuf.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import game.net.util.Recycler; -import game.net.util.internal.PlatformDependent; - -final class PooledUnsafeDirectByteBuf extends PooledByteBuf { - - private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PooledUnsafeDirectByteBuf newObject(Handle handle) { - return new PooledUnsafeDirectByteBuf(handle, 0); - } - }; - - static PooledUnsafeDirectByteBuf newInstance(int maxCapacity) { - PooledUnsafeDirectByteBuf buf = RECYCLER.get(); - buf.setRefCnt(1); - buf.maxCapacity(maxCapacity); - return buf; - } - - private long memoryAddress; - - private PooledUnsafeDirectByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(recyclerHandle, maxCapacity); - } - - @Override - void init(PoolChunk chunk, long handle, int offset, int length, int maxLength) { - super.init(chunk, handle, offset, length, maxLength); - initMemoryAddress(); - } - - @Override - void initUnpooled(PoolChunk chunk, int length) { - super.initUnpooled(chunk, length); - initMemoryAddress(); - } - - private void initMemoryAddress() { - memoryAddress = PlatformDependent.directBufferAddress(memory) + offset; - } - - @Override - protected ByteBuffer newInternalNioBuffer(ByteBuffer memory) { - return memory.duplicate(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - protected byte _getByte(int index) { - return PlatformDependent.getByte(addr(index)); - } - - @Override - protected short _getShort(int index) { - short v = PlatformDependent.getShort(addr(index)); - return NATIVE_ORDER? v : Short.reverseBytes(v); - } - - @Override - protected int _getUnsignedMedium(int index) { - long addr = addr(index); - return (PlatformDependent.getByte(addr) & 0xff) << 16 | - (PlatformDependent.getByte(addr + 1) & 0xff) << 8 | - PlatformDependent.getByte(addr + 2) & 0xff; - } - - @Override - protected int _getInt(int index) { - int v = PlatformDependent.getInt(addr(index)); - return NATIVE_ORDER? v : Integer.reverseBytes(v); - } - - @Override - protected long _getLong(int index) { - long v = PlatformDependent.getLong(addr(index)); - return NATIVE_ORDER? v : Long.reverseBytes(v); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.capacity() - length) { - throw new IndexOutOfBoundsException("dstIndex: " + dstIndex); - } - - if (length != 0) { - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, this, index, length); - } - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.length - length) { - throw new IndexOutOfBoundsException("dstIndex: " + dstIndex); - } - if (length != 0) { - PlatformDependent.copyMemory(addr(index), dst, dstIndex, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - getBytes(index, dst, false); - return this; - } - - private void getBytes(int index, ByteBuffer dst, boolean internal) { - checkIndex(index); - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - if (length != 0) { - byte[] tmp = new byte[length]; - PlatformDependent.copyMemory(addr(index), tmp, 0, length); - out.write(tmp); - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - checkIndex(index, length); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) - throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - protected void _setByte(int index, int value) { - PlatformDependent.putByte(addr(index), (byte) value); - } - - @Override - protected void _setShort(int index, int value) { - PlatformDependent.putShort(addr(index), NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value)); - } - - @Override - protected void _setMedium(int index, int value) { - long addr = addr(index); - PlatformDependent.putByte(addr, (byte) (value >>> 16)); - PlatformDependent.putByte(addr + 1, (byte) (value >>> 8)); - PlatformDependent.putByte(addr + 2, (byte) value); - } - - @Override - protected void _setInt(int index, int value) { - PlatformDependent.putInt(addr(index), NATIVE_ORDER ? value : Integer.reverseBytes(value)); - } - - @Override - protected void _setLong(int index, long value) { - PlatformDependent.putLong(addr(index), NATIVE_ORDER ? value : Long.reverseBytes(value)); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkIndex(index, length); - if (src == null) { - throw new NullPointerException("src"); - } - if (srcIndex < 0 || srcIndex > src.capacity() - length) { - throw new IndexOutOfBoundsException("srcIndex: " + srcIndex); - } - - if (length != 0) { - if (src.hasMemoryAddress()) { - PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr(index), length); - } else if (src.hasArray()) { - PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr(index), length); - } else { - src.getBytes(srcIndex, this, index, length); - } - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkIndex(index, length); - if (length != 0) { - PlatformDependent.copyMemory(src, srcIndex, addr(index), length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - checkIndex(index, src.remaining()); - ByteBuffer tmpBuf = internalNioBuffer(); - if (src == tmpBuf) { - src = src.duplicate(); - } - - index = idx(index); - tmpBuf.clear().position(index).limit(index + src.remaining()); - tmpBuf.put(src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - byte[] tmp = new byte[length]; - int readBytes = in.read(tmp); - if (readBytes > 0) { - PlatformDependent.copyMemory(tmp, 0, addr(index), readBytes); - } - return readBytes; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - ByteBuffer tmpBuf = internalNioBuffer(); - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().directBuffer(length, maxCapacity()); - if (length != 0) { - if (copy.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), copy.memoryAddress(), length); - copy.setIndex(0, length); - } else { - copy.writeBytes(this, index, length); - } - } - return copy; - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return ((ByteBuffer) memory.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return true; - } - - @Override - public long memoryAddress() { - return memoryAddress; - } - - private long addr(int index) { - return memoryAddress + index; - } - - @Override - protected Recycler recycler() { - return RECYCLER; - } - - @Override - protected SwappedByteBuf newSwappedByteBuf() { - return new UnsafeDirectSwappedByteBuf(this); - } -} diff --git a/java/src/game/net/buffer/ReadOnlyByteBuf.java b/java/src/game/net/buffer/ReadOnlyByteBuf.java deleted file mode 100644 index 2c7a196..0000000 --- a/java/src/game/net/buffer/ReadOnlyByteBuf.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -/** - * A derived buffer which forbids any write requests to its parent. It is - * recommended to use {@link Unpooled#unmodifiableBuffer(ByteBuf)} - * instead of calling the constructor explicitly. - */ -public class ReadOnlyByteBuf extends AbstractDerivedByteBuf { - - private final ByteBuf buffer; - - public ReadOnlyByteBuf(ByteBuf buffer) { - super(buffer.maxCapacity()); - - if (buffer instanceof ReadOnlyByteBuf || buffer instanceof DuplicatedByteBuf) { - this.buffer = buffer.unwrap(); - } else { - this.buffer = buffer; - } - setIndex(buffer.readerIndex(), buffer.writerIndex()); - } - - @Override - public boolean isWritable() { - return false; - } - - @Override - public boolean isWritable(int numBytes) { - return false; - } - - @Override - public ByteBuf unwrap() { - return buffer; - } - - @Override - public ByteBufAllocator alloc() { - return buffer.alloc(); - } - - @Override - public ByteOrder order() { - return buffer.order(); - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new ReadOnlyBufferException(); - } - - @Override - public int arrayOffset() { - throw new ReadOnlyBufferException(); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf discardReadBytes() { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, InputStream in, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - return buffer.getBytes(index, out, length); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) - throws IOException { - buffer.getBytes(index, out, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buffer.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf duplicate() { - return new ReadOnlyByteBuf(this); - } - - @Override - public ByteBuf copy(int index, int length) { - return buffer.copy(index, length); - } - - @Override - public ByteBuf slice(int index, int length) { - return Unpooled.unmodifiableBuffer(buffer.slice(index, length)); - } - - @Override - public byte getByte(int index) { - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.getByte(index); - } - - @Override - public short getShort(int index) { - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return buffer.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public int nioBufferCount() { - return buffer.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return buffer.nioBuffer(index, length).asReadOnlyBuffer(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return buffer.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByteDesc(index, length, processor); - } - - @Override - public int capacity() { - return buffer.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new ReadOnlyBufferException(); - } -} diff --git a/java/src/game/net/buffer/ReadOnlyByteBufferBuf.java b/java/src/game/net/buffer/ReadOnlyByteBufferBuf.java deleted file mode 100644 index 0e202c7..0000000 --- a/java/src/game/net/buffer/ReadOnlyByteBufferBuf.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import game.net.util.internal.StringUtil; - - -/** - * Read-only ByteBuf which wraps a read-only ByteBuffer. - */ -class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf { - - protected final ByteBuffer buffer; - private final ByteBufAllocator allocator; - private ByteBuffer tmpNioBuf; - - ReadOnlyByteBufferBuf(ByteBufAllocator allocator, ByteBuffer buffer) { - super(buffer.remaining()); - if (!buffer.isReadOnly()) { - throw new IllegalArgumentException("must be a readonly buffer: " + StringUtil.simpleClassName(buffer)); - } - - this.allocator = allocator; - this.buffer = buffer.slice().order(ByteOrder.BIG_ENDIAN); - writerIndex(this.buffer.limit()); - } - - @Override - protected void deallocate() { } - - @Override - public byte getByte(int index) { - ensureAccessible(); - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.get(index); - } - - @Override - public short getShort(int index) { - ensureAccessible(); - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - ensureAccessible(); - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return (getByte(index) & 0xff) << 16 | (getByte(index + 1) & 0xff) << 8 | getByte(index + 2) & 0xff; - } - - @Override - public int getInt(int index) { - ensureAccessible(); - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - ensureAccessible(); - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else if (dst.nioBufferCount() > 0) { - for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) { - int bbLen = bb.remaining(); - getBytes(index, bb); - index += bbLen; - } - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - - if (dstIndex < 0 || dstIndex > dst.length - length) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length)); - } - - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.get(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex(index); - if (dst == null) { - throw new NullPointerException("dst"); - } - - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - return this; - } - - @Override - protected void _setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - public int capacity() { - return maxCapacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBufAllocator alloc() { - return allocator; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public ByteBuf unwrap() { - return null; - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - ensureAccessible(); - if (length == 0) { - return this; - } - - if (buffer.hasArray()) { - out.write(buffer.array(), index + buffer.arrayOffset(), length); - } else { - byte[] tmp = new byte[length]; - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index); - tmpBuf.get(tmp); - out.write(tmp); - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - ensureAccessible(); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - throw new ReadOnlyBufferException(); - } - - protected final ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = buffer.duplicate(); - } - return tmpNioBuf; - } - - @Override - public ByteBuf copy(int index, int length) { - ensureAccessible(); - ByteBuffer src; - try { - src = (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } catch (IllegalArgumentException ignored) { - throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length)); - } - - ByteBuffer dst = ByteBuffer.allocateDirect(length); - dst.put(src); - dst.order(order()); - dst.clear(); - return new UnpooledDirectByteBuf(alloc(), dst, maxCapacity()); - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return (ByteBuffer) buffer.duplicate().position(index).limit(index + length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - ensureAccessible(); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public boolean hasArray() { - return buffer.hasArray(); - } - - @Override - public byte[] array() { - return buffer.array(); - } - - @Override - public int arrayOffset() { - return buffer.arrayOffset(); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } -} diff --git a/java/src/game/net/buffer/ReadOnlyUnsafeDirectByteBuf.java b/java/src/game/net/buffer/ReadOnlyUnsafeDirectByteBuf.java deleted file mode 100644 index 93ff20b..0000000 --- a/java/src/game/net/buffer/ReadOnlyUnsafeDirectByteBuf.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import game.net.util.internal.PlatformDependent; - - - -/** - * Read-only ByteBuf which wraps a read-only direct ByteBuffer and use unsafe for best performance. - */ -final class ReadOnlyUnsafeDirectByteBuf extends ReadOnlyByteBufferBuf { - private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - private final long memoryAddress; - - ReadOnlyUnsafeDirectByteBuf(ByteBufAllocator allocator, ByteBuffer buffer) { - super(allocator, buffer); - memoryAddress = PlatformDependent.directBufferAddress(buffer); - } - - @Override - protected byte _getByte(int index) { - return PlatformDependent.getByte(addr(index)); - } - - @Override - protected short _getShort(int index) { - short v = PlatformDependent.getShort(addr(index)); - return NATIVE_ORDER? v : Short.reverseBytes(v); - } - - @Override - protected int _getUnsignedMedium(int index) { - long addr = addr(index); - return (PlatformDependent.getByte(addr) & 0xff) << 16 | - (PlatformDependent.getByte(addr + 1) & 0xff) << 8 | - PlatformDependent.getByte(addr + 2) & 0xff; - } - - @Override - protected int _getInt(int index) { - int v = PlatformDependent.getInt(addr(index)); - return NATIVE_ORDER? v : Integer.reverseBytes(v); - } - - @Override - protected long _getLong(int index) { - long v = PlatformDependent.getLong(addr(index)); - return NATIVE_ORDER? v : Long.reverseBytes(v); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.capacity() - length) { - throw new IndexOutOfBoundsException("dstIndex: " + dstIndex); - } - - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.length - length) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length)); - } - - if (length != 0) { - PlatformDependent.copyMemory(addr(index), dst, dstIndex, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex(index); - if (dst == null) { - throw new NullPointerException("dst"); - } - - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - return this; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().directBuffer(length, maxCapacity()); - if (length != 0) { - if (copy.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), copy.memoryAddress(), length); - copy.setIndex(0, length); - } else { - copy.writeBytes(this, index, length); - } - } - return copy; - } - - private long addr(int index) { - return memoryAddress + index; - } -} diff --git a/java/src/game/net/buffer/SimpleLeakAwareByteBuf.java b/java/src/game/net/buffer/SimpleLeakAwareByteBuf.java deleted file mode 100644 index deec8b3..0000000 --- a/java/src/game/net/buffer/SimpleLeakAwareByteBuf.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.nio.ByteOrder; - -import game.net.util.ResourceLeak; - -final class SimpleLeakAwareByteBuf extends WrappedByteBuf { - - private final ResourceLeak leak; - - SimpleLeakAwareByteBuf(ByteBuf buf, ResourceLeak leak) { - super(buf); - this.leak = leak; - } - - @Override - public boolean release() { - boolean deallocated = super.release(); - if (deallocated) { - leak.close(); - } - return deallocated; - } - - @Override - public boolean release(int decrement) { - boolean deallocated = super.release(decrement); - if (deallocated) { - leak.close(); - } - return deallocated; - } - - @Override - public ByteBuf order(ByteOrder endianness) { - leak.record(); - if (order() == endianness) { - return this; - } else { - return new SimpleLeakAwareByteBuf(super.order(endianness), leak); - } - } - - @Override - public ByteBuf slice() { - return new SimpleLeakAwareByteBuf(super.slice(), leak); - } - - @Override - public ByteBuf slice(int index, int length) { - return new SimpleLeakAwareByteBuf(super.slice(index, length), leak); - } - - @Override - public ByteBuf duplicate() { - return new SimpleLeakAwareByteBuf(super.duplicate(), leak); - } - - @Override - public ByteBuf readSlice(int length) { - return new SimpleLeakAwareByteBuf(super.readSlice(length), leak); - } -} diff --git a/java/src/game/net/buffer/SlicedByteBuf.java b/java/src/game/net/buffer/SlicedByteBuf.java deleted file mode 100644 index ce2cdd7..0000000 --- a/java/src/game/net/buffer/SlicedByteBuf.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - - -/** - * A derived buffer which exposes its parent's sub-region only. It is - * recommended to use {@link ByteBuf#slice()} and - * {@link ByteBuf#slice(int, int)} instead of calling the constructor - * explicitly. - */ -public class SlicedByteBuf extends AbstractDerivedByteBuf { - - private final ByteBuf buffer; - private final int adjustment; - private final int length; - - public SlicedByteBuf(ByteBuf buffer, int index, int length) { - super(length); - if (index < 0 || index > buffer.capacity() - length) { - throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')'); - } - - if (buffer instanceof SlicedByteBuf) { - this.buffer = ((SlicedByteBuf) buffer).buffer; - adjustment = ((SlicedByteBuf) buffer).adjustment + index; - } else if (buffer instanceof DuplicatedByteBuf) { - this.buffer = buffer.unwrap(); - adjustment = index; - } else { - this.buffer = buffer; - adjustment = index; - } - this.length = length; - - writerIndex(length); - } - - @Override - public ByteBuf unwrap() { - return buffer; - } - - @Override - public ByteBufAllocator alloc() { - return buffer.alloc(); - } - - @Override - public ByteOrder order() { - return buffer.order(); - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public int capacity() { - return length; - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new UnsupportedOperationException("sliced buffer"); - } - - @Override - public boolean hasArray() { - return buffer.hasArray(); - } - - @Override - public byte[] array() { - return buffer.array(); - } - - @Override - public int arrayOffset() { - return buffer.arrayOffset() + adjustment; - } - - @Override - public boolean hasMemoryAddress() { - return buffer.hasMemoryAddress(); - } - - @Override - public long memoryAddress() { - return buffer.memoryAddress() + adjustment; - } - - @Override - protected byte _getByte(int index) { - return buffer.getByte(index + adjustment); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index + adjustment); - } - - @Override - protected int _getUnsignedMedium(int index) { - return buffer.getUnsignedMedium(index + adjustment); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index + adjustment); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index + adjustment); - } - - @Override - public ByteBuf duplicate() { - ByteBuf duplicate = buffer.slice(adjustment, length); - duplicate.setIndex(readerIndex(), writerIndex()); - return duplicate; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - return buffer.copy(index + adjustment, length); - } - - @Override - public ByteBuf slice(int index, int length) { - checkIndex(index, length); - if (length == 0) { - return Unpooled.EMPTY_BUFFER; - } - return buffer.slice(index + adjustment, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkIndex(index, length); - buffer.getBytes(index + adjustment, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkIndex(index, length); - buffer.getBytes(index + adjustment, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex(index, dst.remaining()); - buffer.getBytes(index + adjustment, dst); - return this; - } - - @Override - protected void _setByte(int index, int value) { - buffer.setByte(index + adjustment, value); - } - - @Override - protected void _setShort(int index, int value) { - buffer.setShort(index + adjustment, value); - } - - @Override - protected void _setMedium(int index, int value) { - buffer.setMedium(index + adjustment, value); - } - - @Override - protected void _setInt(int index, int value) { - buffer.setInt(index + adjustment, value); - } - - @Override - protected void _setLong(int index, long value) { - buffer.setLong(index + adjustment, value); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkIndex(index, length); - buffer.setBytes(index + adjustment, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkIndex(index, length); - buffer.setBytes(index + adjustment, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - checkIndex(index, src.remaining()); - buffer.setBytes(index + adjustment, src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - buffer.getBytes(index + adjustment, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - checkIndex(index, length); - return buffer.getBytes(index + adjustment, out, length); - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - return buffer.setBytes(index + adjustment, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - return buffer.setBytes(index + adjustment, in, length); - } - - @Override - public int nioBufferCount() { - return buffer.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return buffer.nioBuffer(index + adjustment, length); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - return buffer.nioBuffers(index + adjustment, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return nioBuffer(index, length); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - int ret = buffer.forEachByte(index + adjustment, length, processor); - if (ret >= adjustment) { - return ret - adjustment; - } else { - return -1; - } - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - int ret = buffer.forEachByteDesc(index + adjustment, length, processor); - if (ret >= adjustment) { - return ret - adjustment; - } else { - return -1; - } - } -} diff --git a/java/src/game/net/buffer/SwappedByteBuf.java b/java/src/game/net/buffer/SwappedByteBuf.java deleted file mode 100644 index 9fc39bc..0000000 --- a/java/src/game/net/buffer/SwappedByteBuf.java +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -/** - * Wrapper which swap the {@link ByteOrder} of a {@link ByteBuf}. - */ -public class SwappedByteBuf extends ByteBuf { - - private final ByteBuf buf; - private final ByteOrder order; - - public SwappedByteBuf(ByteBuf buf) { - if (buf == null) { - throw new NullPointerException("buf"); - } - this.buf = buf; - if (buf.order() == ByteOrder.BIG_ENDIAN) { - order = ByteOrder.LITTLE_ENDIAN; - } else { - order = ByteOrder.BIG_ENDIAN; - } - } - - @Override - public ByteOrder order() { - return order; - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order) { - return this; - } - return buf; - } - - @Override - public ByteBuf unwrap() { - return buf.unwrap(); - } - - @Override - public ByteBufAllocator alloc() { - return buf.alloc(); - } - - @Override - public int capacity() { - return buf.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - buf.capacity(newCapacity); - return this; - } - - @Override - public int maxCapacity() { - return buf.maxCapacity(); - } - - @Override - public boolean isDirect() { - return buf.isDirect(); - } - - @Override - public int readerIndex() { - return buf.readerIndex(); - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - buf.readerIndex(readerIndex); - return this; - } - - @Override - public int writerIndex() { - return buf.writerIndex(); - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - buf.writerIndex(writerIndex); - return this; - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - buf.setIndex(readerIndex, writerIndex); - return this; - } - - @Override - public int readableBytes() { - return buf.readableBytes(); - } - - @Override - public int writableBytes() { - return buf.writableBytes(); - } - - @Override - public int maxWritableBytes() { - return buf.maxWritableBytes(); - } - - @Override - public boolean isReadable() { - return buf.isReadable(); - } - - @Override - public boolean isReadable(int size) { - return buf.isReadable(size); - } - - @Override - public boolean isWritable() { - return buf.isWritable(); - } - - @Override - public boolean isWritable(int size) { - return buf.isWritable(size); - } - - @Override - public ByteBuf clear() { - buf.clear(); - return this; - } - - @Override - public ByteBuf markReaderIndex() { - buf.markReaderIndex(); - return this; - } - - @Override - public ByteBuf resetReaderIndex() { - buf.resetReaderIndex(); - return this; - } - - @Override - public ByteBuf markWriterIndex() { - buf.markWriterIndex(); - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - buf.resetWriterIndex(); - return this; - } - - @Override - public ByteBuf discardReadBytes() { - buf.discardReadBytes(); - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - buf.discardSomeReadBytes(); - return this; - } - - @Override - public ByteBuf ensureWritable(int writableBytes) { - buf.ensureWritable(writableBytes); - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - return buf.ensureWritable(minWritableBytes, force); - } - - @Override - public boolean getBoolean(int index) { - return buf.getBoolean(index); - } - - @Override - public byte getByte(int index) { - return buf.getByte(index); - } - - @Override - public short getUnsignedByte(int index) { - return buf.getUnsignedByte(index); - } - - @Override - public short getShort(int index) { - return ByteBufUtil.swapShort(buf.getShort(index)); - } - - @Override - public int getUnsignedShort(int index) { - return getShort(index) & 0xFFFF; - } - - @Override - public int getMedium(int index) { - return ByteBufUtil.swapMedium(buf.getMedium(index)); - } - - @Override - public int getUnsignedMedium(int index) { - return getMedium(index) & 0xFFFFFF; - } - - @Override - public int getInt(int index) { - return ByteBufUtil.swapInt(buf.getInt(index)); - } - - @Override - public long getUnsignedInt(int index) { - return getInt(index) & 0xFFFFFFFFL; - } - - @Override - public long getLong(int index) { - return ByteBufUtil.swapLong(buf.getLong(index)); - } - - @Override - public char getChar(int index) { - return (char) getShort(index); - } - - @Override - public float getFloat(int index) { - return Float.intBitsToFloat(getInt(index)); - } - - @Override - public double getDouble(int index) { - return Double.longBitsToDouble(getLong(index)); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - buf.getBytes(index, dst, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - buf.getBytes(index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return buf.getBytes(index, out, length); - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - buf.setBoolean(index, value); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - buf.setByte(index, value); - return this; - } - - @Override - public ByteBuf setShort(int index, int value) { - buf.setShort(index, ByteBufUtil.swapShort((short) value)); - return this; - } - - @Override - public ByteBuf setMedium(int index, int value) { - buf.setMedium(index, ByteBufUtil.swapMedium(value)); - return this; - } - - @Override - public ByteBuf setInt(int index, int value) { - buf.setInt(index, ByteBufUtil.swapInt(value)); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - buf.setLong(index, ByteBufUtil.swapLong(value)); - return this; - } - - @Override - public ByteBuf setChar(int index, int value) { - setShort(index, value); - return this; - } - - @Override - public ByteBuf setFloat(int index, float value) { - setInt(index, Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf setDouble(int index, double value) { - setLong(index, Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - buf.setBytes(index, src, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - buf.setBytes(index, src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public ByteBuf setZero(int index, int length) { - buf.setZero(index, length); - return this; - } - - @Override - public boolean readBoolean() { - return buf.readBoolean(); - } - - @Override - public byte readByte() { - return buf.readByte(); - } - - @Override - public short readUnsignedByte() { - return buf.readUnsignedByte(); - } - - @Override - public short readShort() { - return ByteBufUtil.swapShort(buf.readShort()); - } - - @Override - public int readUnsignedShort() { - return readShort() & 0xFFFF; - } - - @Override - public int readMedium() { - return ByteBufUtil.swapMedium(buf.readMedium()); - } - - @Override - public int readUnsignedMedium() { - return readMedium() & 0xFFFFFF; - } - - @Override - public int readInt() { - return ByteBufUtil.swapInt(buf.readInt()); - } - - @Override - public long readUnsignedInt() { - return readInt() & 0xFFFFFFFFL; - } - - @Override - public long readLong() { - return ByteBufUtil.swapLong(buf.readLong()); - } - - @Override - public char readChar() { - return (char) readShort(); - } - - @Override - public float readFloat() { - return Float.intBitsToFloat(readInt()); - } - - @Override - public double readDouble() { - return Double.longBitsToDouble(readLong()); - } - - @Override - public ByteBuf readBytes(int length) { - return buf.readBytes(length).order(order()); - } - - @Override - public ByteBuf readSlice(int length) { - return buf.readSlice(length).order(order); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - buf.readBytes(dst, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - buf.readBytes(out, length); - return this; - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - return buf.readBytes(out, length); - } - - @Override - public ByteBuf skipBytes(int length) { - buf.skipBytes(length); - return this; - } - - @Override - public ByteBuf writeBoolean(boolean value) { - buf.writeBoolean(value); - return this; - } - - @Override - public ByteBuf writeByte(int value) { - buf.writeByte(value); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - buf.writeShort(ByteBufUtil.swapShort((short) value)); - return this; - } - - @Override - public ByteBuf writeMedium(int value) { - buf.writeMedium(ByteBufUtil.swapMedium(value)); - return this; - } - - @Override - public ByteBuf writeInt(int value) { - buf.writeInt(ByteBufUtil.swapInt(value)); - return this; - } - - @Override - public ByteBuf writeLong(long value) { - buf.writeLong(ByteBufUtil.swapLong(value)); - return this; - } - - @Override - public ByteBuf writeChar(int value) { - writeShort(value); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - writeInt(Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - writeLong(Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - buf.writeBytes(src, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - buf.writeBytes(src); - return this; - } - - @Override - public int writeBytes(InputStream in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public ByteBuf writeZero(int length) { - buf.writeZero(length); - return this; - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - return buf.indexOf(fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - return buf.bytesBefore(value); - } - - @Override - public int bytesBefore(int length, byte value) { - return buf.bytesBefore(length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - return buf.bytesBefore(index, length, value); - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - return buf.forEachByte(processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buf.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - return buf.forEachByteDesc(processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buf.forEachByteDesc(index, length, processor); - } - - @Override - public ByteBuf copy() { - return buf.copy().order(order); - } - - @Override - public ByteBuf copy(int index, int length) { - return buf.copy(index, length).order(order); - } - - @Override - public ByteBuf slice() { - return buf.slice().order(order); - } - - @Override - public ByteBuf slice(int index, int length) { - return buf.slice(index, length).order(order); - } - - @Override - public ByteBuf duplicate() { - return buf.duplicate().order(order); - } - - @Override - public int nioBufferCount() { - return buf.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer() { - return buf.nioBuffer().order(order); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return buf.nioBuffer(index, length).order(order); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers() { - ByteBuffer[] nioBuffers = buf.nioBuffers(); - for (int i = 0; i < nioBuffers.length; i++) { - nioBuffers[i] = nioBuffers[i].order(order); - } - return nioBuffers; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - ByteBuffer[] nioBuffers = buf.nioBuffers(index, length); - for (int i = 0; i < nioBuffers.length; i++) { - nioBuffers[i] = nioBuffers[i].order(order); - } - return nioBuffers; - } - - @Override - public boolean hasArray() { - return buf.hasArray(); - } - - @Override - public byte[] array() { - return buf.array(); - } - - @Override - public int arrayOffset() { - return buf.arrayOffset(); - } - - @Override - public boolean hasMemoryAddress() { - return buf.hasMemoryAddress(); - } - - @Override - public long memoryAddress() { - return buf.memoryAddress(); - } - - @Override - public String toString(Charset charset) { - return buf.toString(charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - return buf.toString(index, length, charset); - } - - @Override - public int refCnt() { - return buf.refCnt(); - } - - @Override - public ByteBuf retain() { - buf.retain(); - return this; - } - - @Override - public ByteBuf retain(int increment) { - buf.retain(increment); - return this; - } - - @Override - public boolean release() { - return buf.release(); - } - - @Override - public boolean release(int decrement) { - return buf.release(decrement); - } - - @Override - public int hashCode() { - return buf.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof ByteBuf) { - return ByteBufUtil.equals(this, (ByteBuf) obj); - } - return false; - } - - @Override - public int compareTo(ByteBuf buffer) { - return ByteBufUtil.compare(this, buffer); - } - - @Override - public String toString() { - return "Swapped(" + buf.toString() + ')'; - } -} diff --git a/java/src/game/net/buffer/Unpooled.java b/java/src/game/net/buffer/Unpooled.java deleted file mode 100644 index 52bae3a..0000000 --- a/java/src/game/net/buffer/Unpooled.java +++ /dev/null @@ -1,861 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; - -import game.net.util.internal.PlatformDependent; - - -/** - * Creates a new {@link ByteBuf} by allocating new space or by wrapping - * or copying existing byte arrays, byte buffers and a string. - * - *

Use static import

- * This classes is intended to be used with Java 5 static import statement: - * - *
- * import static io.netty.buffer.{@link Unpooled}.*;
- *
- * {@link ByteBuf} heapBuffer    = buffer(128);
- * {@link ByteBuf} directBuffer  = directBuffer(256);
- * {@link ByteBuf} wrappedBuffer = wrappedBuffer(new byte[128], new byte[256]);
- * {@link ByteBuf} copiedBuffe r = copiedBuffer({@link ByteBuffer}.allocate(128));
- * 
- * - *

Allocating a new buffer

- * - * Three buffer types are provided out of the box. - * - *
    - *
  • {@link #buffer(int)} allocates a new fixed-capacity heap buffer.
  • - *
  • {@link #directBuffer(int)} allocates a new fixed-capacity direct buffer.
  • - *
- * - *

Creating a wrapped buffer

- * - * Wrapped buffer is a buffer which is a view of one or more existing - * byte arrays and byte buffers. Any changes in the content of the original - * array or buffer will be visible in the wrapped buffer. Various wrapper - * methods are provided and their name is all {@code wrappedBuffer()}. - * You might want to take a look at the methods that accept varargs closely if - * you want to create a buffer which is composed of more than one array to - * reduce the number of memory copy. - * - *

Creating a copied buffer

- * - * Copied buffer is a deep copy of one or more existing byte arrays, byte - * buffers or a string. Unlike a wrapped buffer, there's no shared data - * between the original data and the copied buffer. Various copy methods are - * provided and their name is all {@code copiedBuffer()}. It is also convenient - * to use this operation to merge multiple buffers into one buffer. - * - *

Miscellaneous utility methods

- * - * This class also provides various utility methods to help implementation - * of a new buffer type, generation of hex dump and swapping an integer's - * byte order. - */ -public final class Unpooled { - - private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.DEFAULT; - - /** - * Big endian byte order. - */ - public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN; - - /** - * Little endian byte order. - */ - public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN; - - /** - * A buffer whose capacity is {@code 0}. - */ - public static final ByteBuf EMPTY_BUFFER = ALLOC.buffer(0, 0); - - /** - * Creates a new big-endian Java heap buffer with reasonably small initial capacity, which - * expands its capacity boundlessly on demand. - */ - public static ByteBuf buffer() { - return ALLOC.heapBuffer(); - } - - /** - * Creates a new big-endian direct buffer with reasonably small initial capacity, which - * expands its capacity boundlessly on demand. - */ - public static ByteBuf directBuffer() { - return ALLOC.directBuffer(); - } - - /** - * Creates a new big-endian Java heap buffer with the specified {@code capacity}, which - * expands its capacity boundlessly on demand. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0}. - */ - public static ByteBuf buffer(int initialCapacity) { - return ALLOC.heapBuffer(initialCapacity); - } - - /** - * Creates a new big-endian direct buffer with the specified {@code capacity}, which - * expands its capacity boundlessly on demand. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0}. - */ - public static ByteBuf directBuffer(int initialCapacity) { - return ALLOC.directBuffer(initialCapacity); - } - - /** - * Creates a new big-endian Java heap buffer with the specified - * {@code initialCapacity}, that may grow up to {@code maxCapacity} - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0}. - */ - public static ByteBuf buffer(int initialCapacity, int maxCapacity) { - return ALLOC.heapBuffer(initialCapacity, maxCapacity); - } - - /** - * Creates a new big-endian direct buffer with the specified - * {@code initialCapacity}, that may grow up to {@code maxCapacity}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0}. - */ - public static ByteBuf directBuffer(int initialCapacity, int maxCapacity) { - return ALLOC.directBuffer(initialCapacity, maxCapacity); - } - - /** - * Creates a new big-endian buffer which wraps the specified {@code array}. - * A modification on the specified array's content will be visible to the - * returned buffer. - */ - public static ByteBuf wrappedBuffer(byte[] array) { - if (array.length == 0) { - return EMPTY_BUFFER; - } - return new UnpooledHeapByteBuf(ALLOC, array, array.length); - } - - /** - * Creates a new big-endian buffer which wraps the sub-region of the - * specified {@code array}. A modification on the specified array's - * content will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(byte[] array, int offset, int length) { - if (length == 0) { - return EMPTY_BUFFER; - } - - if (offset == 0 && length == array.length) { - return wrappedBuffer(array); - } - - return wrappedBuffer(array).slice(offset, length); - } - - /** - * Creates a new buffer which wraps the specified NIO buffer's current - * slice. A modification on the specified buffer's content will be - * visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuffer buffer) { - if (!buffer.hasRemaining()) { - return EMPTY_BUFFER; - } - if (buffer.hasArray()) { - return wrappedBuffer( - buffer.array(), - buffer.arrayOffset() + buffer.position(), - buffer.remaining()).order(buffer.order()); - } else if (PlatformDependent.hasUnsafe()) { - if (buffer.isReadOnly()) { - if (buffer.isDirect()) { - return new ReadOnlyUnsafeDirectByteBuf(ALLOC, buffer); - } else { - return new ReadOnlyByteBufferBuf(ALLOC, buffer); - } - } else { - return new UnpooledUnsafeDirectByteBuf(ALLOC, buffer, buffer.remaining()); - } - } else { - if (buffer.isReadOnly()) { - return new ReadOnlyByteBufferBuf(ALLOC, buffer); - } else { - return new UnpooledDirectByteBuf(ALLOC, buffer, buffer.remaining()); - } - } - } - - /** - * Creates a new buffer which wraps the specified buffer's readable bytes. - * A modification on the specified buffer's content will be visible to the - * returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuf buffer) { - if (buffer.isReadable()) { - return buffer.slice(); - } else { - return EMPTY_BUFFER; - } - } - - /** - * Creates a new big-endian composite buffer which wraps the specified - * arrays without copying them. A modification on the specified arrays' - * content will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(byte[]... arrays) { - return wrappedBuffer(16, arrays); - } - - /** - * Creates a new big-endian composite buffer which wraps the readable bytes of the - * specified buffers without copying them. A modification on the content - * of the specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuf... buffers) { - return wrappedBuffer(16, buffers); - } - - /** - * Creates a new big-endian composite buffer which wraps the slices of the specified - * NIO buffers without copying them. A modification on the content of the - * specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuffer... buffers) { - return wrappedBuffer(16, buffers); - } - - /** - * Creates a new big-endian composite buffer which wraps the specified - * arrays without copying them. A modification on the specified arrays' - * content will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(int maxNumComponents, byte[]... arrays) { - switch (arrays.length) { - case 0: - break; - case 1: - if (arrays[0].length != 0) { - return wrappedBuffer(arrays[0]); - } - break; - default: - // Get the list of the component, while guessing the byte order. - final List components = new ArrayList(arrays.length); - for (byte[] a: arrays) { - if (a == null) { - break; - } - if (a.length > 0) { - components.add(wrappedBuffer(a)); - } - } - - if (!components.isEmpty()) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents, components); - } - } - - return EMPTY_BUFFER; - } - - /** - * Creates a new big-endian composite buffer which wraps the readable bytes of the - * specified buffers without copying them. A modification on the content - * of the specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuf... buffers) { - switch (buffers.length) { - case 0: - break; - case 1: - if (buffers[0].isReadable()) { - return wrappedBuffer(buffers[0].order(BIG_ENDIAN)); - } - break; - default: - for (ByteBuf b: buffers) { - if (b.isReadable()) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents, buffers); - } - } - } - return EMPTY_BUFFER; - } - - /** - * Creates a new big-endian composite buffer which wraps the slices of the specified - * NIO buffers without copying them. A modification on the content of the - * specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuffer... buffers) { - switch (buffers.length) { - case 0: - break; - case 1: - if (buffers[0].hasRemaining()) { - return wrappedBuffer(buffers[0].order(BIG_ENDIAN)); - } - break; - default: - // Get the list of the component, while guessing the byte order. - final List components = new ArrayList(buffers.length); - for (ByteBuffer b: buffers) { - if (b == null) { - break; - } - if (b.remaining() > 0) { - components.add(wrappedBuffer(b.order(BIG_ENDIAN))); - } - } - - if (!components.isEmpty()) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents, components); - } - } - - return EMPTY_BUFFER; - } - - /** - * Returns a new big-endian composite buffer with no components. - */ - public static CompositeByteBuf compositeBuffer() { - return compositeBuffer(16); - } - - /** - * Returns a new big-endian composite buffer with no components. - */ - public static CompositeByteBuf compositeBuffer(int maxNumComponents) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents); - } - - /** - * Creates a new big-endian buffer whose content is a copy of the - * specified {@code array}. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0} and {@code array.length} respectively. - */ - public static ByteBuf copiedBuffer(byte[] array) { - if (array.length == 0) { - return EMPTY_BUFFER; - } - return wrappedBuffer(array.clone()); - } - - /** - * Creates a new big-endian buffer whose content is a copy of the - * specified {@code array}'s sub-region. The new buffer's - * {@code readerIndex} and {@code writerIndex} are {@code 0} and - * the specified {@code length} respectively. - */ - public static ByteBuf copiedBuffer(byte[] array, int offset, int length) { - if (length == 0) { - return EMPTY_BUFFER; - } - byte[] copy = new byte[length]; - System.arraycopy(array, offset, copy, 0, length); - return wrappedBuffer(copy); - } - - /** - * Creates a new buffer whose content is a copy of the specified - * {@code buffer}'s current slice. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and {@code buffer.remaining} - * respectively. - */ - public static ByteBuf copiedBuffer(ByteBuffer buffer) { - int length = buffer.remaining(); - if (length == 0) { - return EMPTY_BUFFER; - } - byte[] copy = new byte[length]; - int position = buffer.position(); - try { - buffer.get(copy); - } finally { - buffer.position(position); - } - return wrappedBuffer(copy).order(buffer.order()); - } - - /** - * Creates a new buffer whose content is a copy of the specified - * {@code buffer}'s readable bytes. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and {@code buffer.readableBytes} - * respectively. - */ - public static ByteBuf copiedBuffer(ByteBuf buffer) { - int readable = buffer.readableBytes(); - if (readable > 0) { - ByteBuf copy = buffer(readable); - copy.writeBytes(buffer, buffer.readerIndex(), readable); - return copy; - } else { - return EMPTY_BUFFER; - } - } - - /** - * Creates a new big-endian buffer whose content is a merged copy of - * the specified {@code arrays}. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and the sum of all arrays' - * {@code length} respectively. - */ - public static ByteBuf copiedBuffer(byte[]... arrays) { - switch (arrays.length) { - case 0: - return EMPTY_BUFFER; - case 1: - if (arrays[0].length == 0) { - return EMPTY_BUFFER; - } else { - return copiedBuffer(arrays[0]); - } - } - - // Merge the specified arrays into one array. - int length = 0; - for (byte[] a: arrays) { - if (Integer.MAX_VALUE - length < a.length) { - throw new IllegalArgumentException( - "The total length of the specified arrays is too big."); - } - length += a.length; - } - - if (length == 0) { - return EMPTY_BUFFER; - } - - byte[] mergedArray = new byte[length]; - for (int i = 0, j = 0; i < arrays.length; i ++) { - byte[] a = arrays[i]; - System.arraycopy(a, 0, mergedArray, j, a.length); - j += a.length; - } - - return wrappedBuffer(mergedArray); - } - - /** - * Creates a new buffer whose content is a merged copy of the specified - * {@code buffers}' readable bytes. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and the sum of all buffers' - * {@code readableBytes} respectively. - * - * @throws IllegalArgumentException - * if the specified buffers' endianness are different from each - * other - */ - public static ByteBuf copiedBuffer(ByteBuf... buffers) { - switch (buffers.length) { - case 0: - return EMPTY_BUFFER; - case 1: - return copiedBuffer(buffers[0]); - } - - // Merge the specified buffers into one buffer. - ByteOrder order = null; - int length = 0; - for (ByteBuf b: buffers) { - int bLen = b.readableBytes(); - if (bLen <= 0) { - continue; - } - if (Integer.MAX_VALUE - length < bLen) { - throw new IllegalArgumentException( - "The total length of the specified buffers is too big."); - } - length += bLen; - if (order != null) { - if (!order.equals(b.order())) { - throw new IllegalArgumentException("inconsistent byte order"); - } - } else { - order = b.order(); - } - } - - if (length == 0) { - return EMPTY_BUFFER; - } - - byte[] mergedArray = new byte[length]; - for (int i = 0, j = 0; i < buffers.length; i ++) { - ByteBuf b = buffers[i]; - int bLen = b.readableBytes(); - b.getBytes(b.readerIndex(), mergedArray, j, bLen); - j += bLen; - } - - return wrappedBuffer(mergedArray).order(order); - } - - /** - * Creates a new buffer whose content is a merged copy of the specified - * {@code buffers}' slices. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0} and the sum of all buffers' - * {@code remaining} respectively. - * - * @throws IllegalArgumentException - * if the specified buffers' endianness are different from each - * other - */ - public static ByteBuf copiedBuffer(ByteBuffer... buffers) { - switch (buffers.length) { - case 0: - return EMPTY_BUFFER; - case 1: - return copiedBuffer(buffers[0]); - } - - // Merge the specified buffers into one buffer. - ByteOrder order = null; - int length = 0; - for (ByteBuffer b: buffers) { - int bLen = b.remaining(); - if (bLen <= 0) { - continue; - } - if (Integer.MAX_VALUE - length < bLen) { - throw new IllegalArgumentException( - "The total length of the specified buffers is too big."); - } - length += bLen; - if (order != null) { - if (!order.equals(b.order())) { - throw new IllegalArgumentException("inconsistent byte order"); - } - } else { - order = b.order(); - } - } - - if (length == 0) { - return EMPTY_BUFFER; - } - - byte[] mergedArray = new byte[length]; - for (int i = 0, j = 0; i < buffers.length; i ++) { - ByteBuffer b = buffers[i]; - int bLen = b.remaining(); - int oldPos = b.position(); - b.get(mergedArray, j, bLen); - b.position(oldPos); - j += bLen; - } - - return wrappedBuffer(mergedArray).order(order); - } - - /** - * Creates a new big-endian buffer whose content is the specified - * {@code string} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer(CharSequence string, Charset charset) { - if (string == null) { - throw new NullPointerException("string"); - } - - if (string instanceof CharBuffer) { - return copiedBuffer((CharBuffer) string, charset); - } - - return copiedBuffer(CharBuffer.wrap(string), charset); - } - - /** - * Creates a new big-endian buffer whose content is a subregion of - * the specified {@code string} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer( - CharSequence string, int offset, int length, Charset charset) { - if (string == null) { - throw new NullPointerException("string"); - } - if (length == 0) { - return EMPTY_BUFFER; - } - - if (string instanceof CharBuffer) { - CharBuffer buf = (CharBuffer) string; - if (buf.hasArray()) { - return copiedBuffer( - buf.array(), - buf.arrayOffset() + buf.position() + offset, - length, charset); - } - - buf = buf.slice(); - buf.limit(length); - buf.position(offset); - return copiedBuffer(buf, charset); - } - - return copiedBuffer(CharBuffer.wrap(string, offset, offset + length), charset); - } - - /** - * Creates a new big-endian buffer whose content is the specified - * {@code array} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer(char[] array, Charset charset) { - if (array == null) { - throw new NullPointerException("array"); - } - return copiedBuffer(array, 0, array.length, charset); - } - - /** - * Creates a new big-endian buffer whose content is a subregion of - * the specified {@code array} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer(char[] array, int offset, int length, Charset charset) { - if (array == null) { - throw new NullPointerException("array"); - } - if (length == 0) { - return EMPTY_BUFFER; - } - return copiedBuffer(CharBuffer.wrap(array, offset, length), charset); - } - - private static ByteBuf copiedBuffer(CharBuffer buffer, Charset charset) { - return ByteBufUtil.encodeString0(ALLOC, true, buffer, charset); - } - - /** - * Creates a read-only buffer which disallows any modification operations - * on the specified {@code buffer}. The new buffer has the same - * {@code readerIndex} and {@code writerIndex} with the specified - * {@code buffer}. - */ - public static ByteBuf unmodifiableBuffer(ByteBuf buffer) { - ByteOrder endianness = buffer.order(); - if (endianness == BIG_ENDIAN) { - return new ReadOnlyByteBuf(buffer); - } - - return new ReadOnlyByteBuf(buffer.order(BIG_ENDIAN)).order(LITTLE_ENDIAN); - } - - /** - * Creates a new 4-byte big-endian buffer that holds the specified 32-bit integer. - */ - public static ByteBuf copyInt(int value) { - ByteBuf buf = buffer(4); - buf.writeInt(value); - return buf; - } - - /** - * Create a big-endian buffer that holds a sequence of the specified 32-bit integers. - */ - public static ByteBuf copyInt(int... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 4); - for (int v: values) { - buffer.writeInt(v); - } - return buffer; - } - - /** - * Creates a new 2-byte big-endian buffer that holds the specified 16-bit integer. - */ - public static ByteBuf copyShort(int value) { - ByteBuf buf = buffer(2); - buf.writeShort(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers. - */ - public static ByteBuf copyShort(short... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 2); - for (int v: values) { - buffer.writeShort(v); - } - return buffer; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers. - */ - public static ByteBuf copyShort(int... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 2); - for (int v: values) { - buffer.writeShort(v); - } - return buffer; - } - - /** - * Creates a new 3-byte big-endian buffer that holds the specified 24-bit integer. - */ - public static ByteBuf copyMedium(int value) { - ByteBuf buf = buffer(3); - buf.writeMedium(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 24-bit integers. - */ - public static ByteBuf copyMedium(int... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 3); - for (int v: values) { - buffer.writeMedium(v); - } - return buffer; - } - - /** - * Creates a new 8-byte big-endian buffer that holds the specified 64-bit integer. - */ - public static ByteBuf copyLong(long value) { - ByteBuf buf = buffer(8); - buf.writeLong(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 64-bit integers. - */ - public static ByteBuf copyLong(long... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 8); - for (long v: values) { - buffer.writeLong(v); - } - return buffer; - } - - /** - * Creates a new single-byte big-endian buffer that holds the specified boolean value. - */ - public static ByteBuf copyBoolean(boolean value) { - ByteBuf buf = buffer(1); - buf.writeBoolean(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified boolean values. - */ - public static ByteBuf copyBoolean(boolean... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length); - for (boolean v: values) { - buffer.writeBoolean(v); - } - return buffer; - } - - /** - * Creates a new 4-byte big-endian buffer that holds the specified 32-bit floating point number. - */ - public static ByteBuf copyFloat(float value) { - ByteBuf buf = buffer(4); - buf.writeFloat(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 32-bit floating point numbers. - */ - public static ByteBuf copyFloat(float... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 4); - for (float v: values) { - buffer.writeFloat(v); - } - return buffer; - } - - /** - * Creates a new 8-byte big-endian buffer that holds the specified 64-bit floating point number. - */ - public static ByteBuf copyDouble(double value) { - ByteBuf buf = buffer(8); - buf.writeDouble(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 64-bit floating point numbers. - */ - public static ByteBuf copyDouble(double... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 8); - for (double v: values) { - buffer.writeDouble(v); - } - return buffer; - } - - /** - * Return a unreleasable view on the given {@link ByteBuf} which will just ignore release and retain calls. - */ - public static ByteBuf unreleasableBuffer(ByteBuf buf) { - return new UnreleasableByteBuf(buf); - } - - private Unpooled() { - // Unused - } -} diff --git a/java/src/game/net/buffer/UnpooledByteBufAllocator.java b/java/src/game/net/buffer/UnpooledByteBufAllocator.java deleted file mode 100644 index c425de9..0000000 --- a/java/src/game/net/buffer/UnpooledByteBufAllocator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import game.net.util.internal.PlatformDependent; - -/** - * Simplistic {@link ByteBufAllocator} implementation that does not pool anything. - */ -public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator { - - /** - * Default instance - */ - public static final UnpooledByteBufAllocator DEFAULT = - new UnpooledByteBufAllocator(PlatformDependent.directBufferPreferred()); - - /** - * Create a new instance - * - * @param preferDirect {@code true} if {@link #buffer(int)} should try to allocate a direct buffer rather than - * a heap buffer - */ - public UnpooledByteBufAllocator(boolean preferDirect) { - super(preferDirect); - } - - @Override - protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) { - return new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity); - } - - @Override - protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) { - ByteBuf buf; - if (PlatformDependent.hasUnsafe()) { - buf = new UnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity); - } else { - buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity); - } - - return toLeakAwareBuffer(buf); - } - - @Override - public boolean isDirectBufferPooled() { - return false; - } -} diff --git a/java/src/game/net/buffer/UnpooledDirectByteBuf.java b/java/src/game/net/buffer/UnpooledDirectByteBuf.java deleted file mode 100644 index 89f0c1e..0000000 --- a/java/src/game/net/buffer/UnpooledDirectByteBuf.java +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import game.net.util.internal.PlatformDependent; - -/** - * A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link Unpooled#directBuffer(int)} - * and {@link Unpooled#wrappedBuffer(ByteBuffer)} instead of calling the - * constructor explicitly. - */ -public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf { - - private final ByteBufAllocator alloc; - - private ByteBuffer buffer; - private ByteBuffer tmpNioBuf; - private int capacity; - private boolean doNotFree; - - /** - * Creates a new direct buffer. - * - * @param initialCapacity the initial capacity of the underlying direct buffer - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialCapacity < 0) { - throw new IllegalArgumentException("initialCapacity: " + initialCapacity); - } - if (maxCapacity < 0) { - throw new IllegalArgumentException("maxCapacity: " + maxCapacity); - } - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - setByteBuffer(ByteBuffer.allocateDirect(initialCapacity)); - } - - /** - * Creates a new direct buffer by wrapping the specified initial buffer. - * - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialBuffer == null) { - throw new NullPointerException("initialBuffer"); - } - if (!initialBuffer.isDirect()) { - throw new IllegalArgumentException("initialBuffer is not a direct buffer."); - } - if (initialBuffer.isReadOnly()) { - throw new IllegalArgumentException("initialBuffer is a read-only buffer."); - } - - int initialCapacity = initialBuffer.remaining(); - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - doNotFree = true; - setByteBuffer(initialBuffer.slice().order(ByteOrder.BIG_ENDIAN)); - writerIndex(initialCapacity); - } - - /** - * Allocate a new direct {@link ByteBuffer} with the given initialCapacity. - */ - protected ByteBuffer allocateDirect(int initialCapacity) { - return ByteBuffer.allocateDirect(initialCapacity); - } - - /** - * Free a direct {@link ByteBuffer} - */ - protected void freeDirect(ByteBuffer buffer) { - PlatformDependent.freeDirectBuffer(buffer); - } - - private void setByteBuffer(ByteBuffer buffer) { - ByteBuffer oldBuffer = this.buffer; - if (oldBuffer != null) { - if (doNotFree) { - doNotFree = false; - } else { - freeDirect(oldBuffer); - } - } - - this.buffer = buffer; - tmpNioBuf = null; - capacity = buffer.remaining(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - public int capacity() { - return capacity; - } - - @Override - public ByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int readerIndex = readerIndex(); - int writerIndex = writerIndex(); - - int oldCapacity = capacity; - if (newCapacity > oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - oldBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.put(oldBuffer); - newBuffer.clear(); - setByteBuffer(newBuffer); - } else if (newCapacity < oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - if (readerIndex < newCapacity) { - if (writerIndex > newCapacity) { - writerIndex(writerIndex = newCapacity); - } - oldBuffer.position(readerIndex).limit(writerIndex); - newBuffer.position(readerIndex).limit(writerIndex); - newBuffer.put(oldBuffer); - newBuffer.clear(); - } else { - setIndex(newCapacity, newCapacity); - } - setByteBuffer(newBuffer); - } - return this; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - public byte getByte(int index) { - ensureAccessible(); - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.get(index); - } - - @Override - public short getShort(int index) { - ensureAccessible(); - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - ensureAccessible(); - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return (getByte(index) & 0xff) << 16 | (getByte(index + 1) & 0xff) << 8 | getByte(index + 2) & 0xff; - } - - @Override - public int getInt(int index) { - ensureAccessible(); - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - ensureAccessible(); - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else if (dst.nioBufferCount() > 0) { - for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) { - int bbLen = bb.remaining(); - getBytes(index, bb); - index += bbLen; - } - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - getBytes(index, dst, dstIndex, length, false); - return this; - } - - private void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) { - checkDstIndex(index, length, dstIndex, dst.length); - - if (dstIndex < 0 || dstIndex > dst.length - length) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length)); - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.get(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - getBytes(index, dst, false); - return this; - } - - private void getBytes(int index, ByteBuffer dst, boolean internal) { - checkIndex(index); - if (dst == null) { - throw new NullPointerException("dst"); - } - - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - ensureAccessible(); - _setByte(index, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - buffer.put(index, (byte) value); - } - - @Override - public ByteBuf setShort(int index, int value) { - ensureAccessible(); - _setShort(index, value); - return this; - } - - @Override - protected void _setShort(int index, int value) { - buffer.putShort(index, (short) value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - ensureAccessible(); - _setMedium(index, value); - return this; - } - - @Override - protected void _setMedium(int index, int value) { - setByte(index, (byte) (value >>> 16)); - setByte(index + 1, (byte) (value >>> 8)); - setByte(index + 2, (byte) value); - } - - @Override - public ByteBuf setInt(int index, int value) { - ensureAccessible(); - _setInt(index, value); - return this; - } - - @Override - protected void _setInt(int index, int value) { - buffer.putInt(index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - ensureAccessible(); - _setLong(index, value); - return this; - } - - @Override - protected void _setLong(int index, long value) { - buffer.putLong(index, value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.nioBufferCount() > 0) { - for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) { - int bbLen = bb.remaining(); - setBytes(index, bb); - index += bbLen; - } - } else { - src.getBytes(srcIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.put(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - ensureAccessible(); - ByteBuffer tmpBuf = internalNioBuffer(); - if (src == tmpBuf) { - src = src.duplicate(); - } - - tmpBuf.clear().position(index).limit(index + src.remaining()); - tmpBuf.put(src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - getBytes(index, out, length, false); - return this; - } - - private void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException { - ensureAccessible(); - if (length == 0) { - return; - } - - if (buffer.hasArray()) { - out.write(buffer.array(), index + buffer.arrayOffset(), length); - } else { - byte[] tmp = new byte[length]; - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index); - tmpBuf.get(tmp); - out.write(tmp); - } - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - checkReadableBytes(length); - getBytes(readerIndex, out, length, true); - readerIndex += length; - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - ensureAccessible(); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - ensureAccessible(); - if (buffer.hasArray()) { - return in.read(buffer.array(), buffer.arrayOffset() + index, length); - } else { - byte[] tmp = new byte[length]; - int readBytes = in.read(tmp); - if (readBytes <= 0) { - return readBytes; - } - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index); - tmpBuf.put(tmp, 0, readBytes); - return readBytes; - } - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpNioBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuf copy(int index, int length) { - ensureAccessible(); - ByteBuffer src; - try { - src = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length); - } catch (IllegalArgumentException ignored) { - throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length)); - } - - return alloc().directBuffer(length, maxCapacity()).writeBytes(src); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - private ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = buffer.duplicate(); - } - return tmpNioBuf; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return ((ByteBuffer) buffer.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - protected void deallocate() { - ByteBuffer buffer = this.buffer; - if (buffer == null) { - return; - } - - this.buffer = null; - - if (!doNotFree) { - freeDirect(buffer); - } - } - - @Override - public ByteBuf unwrap() { - return null; - } -} diff --git a/java/src/game/net/buffer/UnpooledHeapByteBuf.java b/java/src/game/net/buffer/UnpooledHeapByteBuf.java deleted file mode 100644 index e97d430..0000000 --- a/java/src/game/net/buffer/UnpooledHeapByteBuf.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import game.net.util.internal.PlatformDependent; - -/** - * Big endian Java heap buffer implementation. - */ -public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf { - - private final ByteBufAllocator alloc; - private byte[] array; - private ByteBuffer tmpNioBuf; - - /** - * Creates a new heap buffer with a newly allocated byte array. - * - * @param initialCapacity the initial capacity of the underlying byte array - * @param maxCapacity the max capacity of the underlying byte array - */ - protected UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { - this(alloc, new byte[initialCapacity], 0, 0, maxCapacity); - } - - /** - * Creates a new heap buffer with an existing byte array. - * - * @param initialArray the initial underlying byte array - * @param maxCapacity the max capacity of the underlying byte array - */ - protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) { - this(alloc, initialArray, 0, initialArray.length, maxCapacity); - } - - private UnpooledHeapByteBuf( - ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) { - - super(maxCapacity); - - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialArray == null) { - throw new NullPointerException("initialArray"); - } - if (initialArray.length > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity)); - } - - this.alloc = alloc; - setArray(initialArray); - setIndex(readerIndex, writerIndex); - } - - private void setArray(byte[] initialArray) { - array = initialArray; - tmpNioBuf = null; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public boolean isDirect() { - return false; - } - - @Override - public int capacity() { - ensureAccessible(); - return array.length; - } - - @Override - public ByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int oldCapacity = array.length; - if (newCapacity > oldCapacity) { - byte[] newArray = new byte[newCapacity]; - System.arraycopy(array, 0, newArray, 0, array.length); - setArray(newArray); - } else if (newCapacity < oldCapacity) { - byte[] newArray = new byte[newCapacity]; - int readerIndex = readerIndex(); - if (readerIndex < newCapacity) { - int writerIndex = writerIndex(); - if (writerIndex > newCapacity) { - writerIndex(writerIndex = newCapacity); - } - System.arraycopy(array, readerIndex, newArray, readerIndex, writerIndex - readerIndex); - } else { - setIndex(newCapacity, newCapacity); - } - setArray(newArray); - } - return this; - } - - @Override - public boolean hasArray() { - return true; - } - - @Override - public byte[] array() { - ensureAccessible(); - return array; - } - - @Override - public int arrayOffset() { - return 0; - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(array, index, dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, array, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - System.arraycopy(array, index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - ensureAccessible(); - dst.put(array, index, Math.min(capacity() - index, dst.remaining())); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - ensureAccessible(); - out.write(array, index, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - ensureAccessible(); - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - ensureAccessible(); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = ByteBuffer.wrap(array); - } - return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length)); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.hasMemoryAddress()) { - PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, array, index, length); - } else if (src.hasArray()) { - setBytes(index, src.array(), src.arrayOffset() + srcIndex, length); - } else { - src.getBytes(srcIndex, array, index, length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - System.arraycopy(src, srcIndex, array, index, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - ensureAccessible(); - src.get(array, index, src.remaining()); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - ensureAccessible(); - return in.read(array, index, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - try { - return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - ensureAccessible(); - return ByteBuffer.wrap(array, index, length).slice(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public byte getByte(int index) { - ensureAccessible(); - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return array[index]; - } - - @Override - public short getShort(int index) { - ensureAccessible(); - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return (short) (array[index] << 8 | array[index + 1] & 0xFF); - } - - @Override - public int getUnsignedMedium(int index) { - ensureAccessible(); - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return (array[index] & 0xff) << 16 | - (array[index + 1] & 0xff) << 8 | - array[index + 2] & 0xff; - } - - @Override - public int getInt(int index) { - ensureAccessible(); - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return (array[index] & 0xff) << 24 | - (array[index + 1] & 0xff) << 16 | - (array[index + 2] & 0xff) << 8 | - array[index + 3] & 0xff; - } - - @Override - public long getLong(int index) { - ensureAccessible(); - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return ((long) array[index] & 0xff) << 56 | - ((long) array[index + 1] & 0xff) << 48 | - ((long) array[index + 2] & 0xff) << 40 | - ((long) array[index + 3] & 0xff) << 32 | - ((long) array[index + 4] & 0xff) << 24 | - ((long) array[index + 5] & 0xff) << 16 | - ((long) array[index + 6] & 0xff) << 8 | - (long) array[index + 7] & 0xff; - } - - @Override - public ByteBuf setByte(int index, int value) { - ensureAccessible(); - _setByte(index, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - array[index] = (byte) value; - } - - @Override - public ByteBuf setShort(int index, int value) { - ensureAccessible(); - _setShort(index, value); - return this; - } - - @Override - protected void _setShort(int index, int value) { - array[index] = (byte) (value >>> 8); - array[index + 1] = (byte) value; - } - - @Override - public ByteBuf setMedium(int index, int value) { - ensureAccessible(); - _setMedium(index, value); - return this; - } - - @Override - protected void _setMedium(int index, int value) { - array[index] = (byte) (value >>> 16); - array[index + 1] = (byte) (value >>> 8); - array[index + 2] = (byte) value; - } - - @Override - public ByteBuf setInt(int index, int value) { - ensureAccessible(); - _setInt(index, value); - return this; - } - - @Override - protected void _setInt(int index, int value) { - array[index] = (byte) (value >>> 24); - array[index + 1] = (byte) (value >>> 16); - array[index + 2] = (byte) (value >>> 8); - array[index + 3] = (byte) value; - } - - @Override - public ByteBuf setLong(int index, long value) { - ensureAccessible(); - _setLong(index, value); - return this; - } - - @Override - protected void _setLong(int index, long value) { - array[index] = (byte) (value >>> 56); - array[index + 1] = (byte) (value >>> 48); - array[index + 2] = (byte) (value >>> 40); - array[index + 3] = (byte) (value >>> 32); - array[index + 4] = (byte) (value >>> 24); - array[index + 5] = (byte) (value >>> 16); - array[index + 6] = (byte) (value >>> 8); - array[index + 7] = (byte) value; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - byte[] copiedArray = new byte[length]; - System.arraycopy(array, index, copiedArray, 0, length); - return new UnpooledHeapByteBuf(alloc(), copiedArray, maxCapacity()); - } - - private ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = ByteBuffer.wrap(array); - } - return tmpNioBuf; - } - - @Override - protected void deallocate() { - array = null; - } - - @Override - public ByteBuf unwrap() { - return null; - } -} diff --git a/java/src/game/net/buffer/UnpooledUnsafeDirectByteBuf.java b/java/src/game/net/buffer/UnpooledUnsafeDirectByteBuf.java deleted file mode 100644 index 6e6bb91..0000000 --- a/java/src/game/net/buffer/UnpooledUnsafeDirectByteBuf.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import game.net.util.internal.PlatformDependent; - -/** - * A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link Unpooled#directBuffer(int)} - * and {@link Unpooled#wrappedBuffer(ByteBuffer)} instead of calling the - * constructor explicitly. - */ -public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf { - - private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - - private final ByteBufAllocator alloc; - - private long memoryAddress; - private ByteBuffer buffer; - private ByteBuffer tmpNioBuf; - private int capacity; - private boolean doNotFree; - - /** - * Creates a new direct buffer. - * - * @param initialCapacity the initial capacity of the underlying direct buffer - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialCapacity < 0) { - throw new IllegalArgumentException("initialCapacity: " + initialCapacity); - } - if (maxCapacity < 0) { - throw new IllegalArgumentException("maxCapacity: " + maxCapacity); - } - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - setByteBuffer(allocateDirect(initialCapacity)); - } - - /** - * Creates a new direct buffer by wrapping the specified initial buffer. - * - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialBuffer == null) { - throw new NullPointerException("initialBuffer"); - } - if (!initialBuffer.isDirect()) { - throw new IllegalArgumentException("initialBuffer is not a direct buffer."); - } - if (initialBuffer.isReadOnly()) { - throw new IllegalArgumentException("initialBuffer is a read-only buffer."); - } - - int initialCapacity = initialBuffer.remaining(); - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - doNotFree = true; - setByteBuffer(initialBuffer.slice().order(ByteOrder.BIG_ENDIAN)); - writerIndex(initialCapacity); - } - - /** - * Allocate a new direct {@link ByteBuffer} with the given initialCapacity. - */ - protected ByteBuffer allocateDirect(int initialCapacity) { - return ByteBuffer.allocateDirect(initialCapacity); - } - - /** - * Free a direct {@link ByteBuffer} - */ - protected void freeDirect(ByteBuffer buffer) { - PlatformDependent.freeDirectBuffer(buffer); - } - - private void setByteBuffer(ByteBuffer buffer) { - ByteBuffer oldBuffer = this.buffer; - if (oldBuffer != null) { - if (doNotFree) { - doNotFree = false; - } else { - freeDirect(oldBuffer); - } - } - - this.buffer = buffer; - memoryAddress = PlatformDependent.directBufferAddress(buffer); - tmpNioBuf = null; - capacity = buffer.remaining(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - public int capacity() { - return capacity; - } - - @Override - public ByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int readerIndex = readerIndex(); - int writerIndex = writerIndex(); - - int oldCapacity = capacity; - if (newCapacity > oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - oldBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.put(oldBuffer); - newBuffer.clear(); - setByteBuffer(newBuffer); - } else if (newCapacity < oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - if (readerIndex < newCapacity) { - if (writerIndex > newCapacity) { - writerIndex(writerIndex = newCapacity); - } - oldBuffer.position(readerIndex).limit(writerIndex); - newBuffer.position(readerIndex).limit(writerIndex); - newBuffer.put(oldBuffer); - newBuffer.clear(); - } else { - setIndex(newCapacity, newCapacity); - } - setByteBuffer(newBuffer); - } - return this; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return true; - } - - @Override - public long memoryAddress() { - return memoryAddress; - } - - @Override - protected byte _getByte(int index) { - return PlatformDependent.getByte(addr(index)); - } - - @Override - protected short _getShort(int index) { - short v = PlatformDependent.getShort(addr(index)); - return NATIVE_ORDER? v : Short.reverseBytes(v); - } - - @Override - protected int _getUnsignedMedium(int index) { - long addr = addr(index); - return (PlatformDependent.getByte(addr) & 0xff) << 16 | - (PlatformDependent.getByte(addr + 1) & 0xff) << 8 | - PlatformDependent.getByte(addr + 2) & 0xff; - } - - @Override - protected int _getInt(int index) { - int v = PlatformDependent.getInt(addr(index)); - return NATIVE_ORDER? v : Integer.reverseBytes(v); - } - - @Override - protected long _getLong(int index) { - long v = PlatformDependent.getLong(addr(index)); - return NATIVE_ORDER? v : Long.reverseBytes(v); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.capacity() - length) { - throw new IndexOutOfBoundsException("dstIndex: " + dstIndex); - } - - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.length - length) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length)); - } - - if (length != 0) { - PlatformDependent.copyMemory(addr(index), dst, dstIndex, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - getBytes(index, dst, false); - return this; - } - - private void getBytes(int index, ByteBuffer dst, boolean internal) { - checkIndex(index); - if (dst == null) { - throw new NullPointerException("dst"); - } - - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst, true); - readerIndex += length; - return this; - } - - @Override - protected void _setByte(int index, int value) { - PlatformDependent.putByte(addr(index), (byte) value); - } - - @Override - protected void _setShort(int index, int value) { - PlatformDependent.putShort(addr(index), NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value)); - } - - @Override - protected void _setMedium(int index, int value) { - long addr = addr(index); - PlatformDependent.putByte(addr, (byte) (value >>> 16)); - PlatformDependent.putByte(addr + 1, (byte) (value >>> 8)); - PlatformDependent.putByte(addr + 2, (byte) value); - } - - @Override - protected void _setInt(int index, int value) { - PlatformDependent.putInt(addr(index), NATIVE_ORDER ? value : Integer.reverseBytes(value)); - } - - @Override - protected void _setLong(int index, long value) { - PlatformDependent.putLong(addr(index), NATIVE_ORDER ? value : Long.reverseBytes(value)); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkIndex(index, length); - if (src == null) { - throw new NullPointerException("src"); - } - if (srcIndex < 0 || srcIndex > src.capacity() - length) { - throw new IndexOutOfBoundsException("srcIndex: " + srcIndex); - } - - if (length != 0) { - if (src.hasMemoryAddress()) { - PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr(index), length); - } else if (src.hasArray()) { - PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr(index), length); - } else { - src.getBytes(srcIndex, this, index, length); - } - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkIndex(index, length); - if (length != 0) { - PlatformDependent.copyMemory(src, srcIndex, addr(index), length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - ensureAccessible(); - ByteBuffer tmpBuf = internalNioBuffer(); - if (src == tmpBuf) { - src = src.duplicate(); - } - - tmpBuf.clear().position(index).limit(index + src.remaining()); - tmpBuf.put(src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - ensureAccessible(); - if (length != 0) { - byte[] tmp = new byte[length]; - PlatformDependent.copyMemory(addr(index), tmp, 0, length); - out.write(tmp); - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - ensureAccessible(); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - byte[] tmp = new byte[length]; - int readBytes = in.read(tmp); - if (readBytes > 0) { - PlatformDependent.copyMemory(tmp, 0, addr(index), readBytes); - } - return readBytes; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().directBuffer(length, maxCapacity()); - if (length != 0) { - if (copy.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), copy.memoryAddress(), length); - copy.setIndex(0, length); - } else { - copy.writeBytes(this, index, length); - } - } - return copy; - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - private ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = buffer.duplicate(); - } - return tmpNioBuf; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return ((ByteBuffer) buffer.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - protected void deallocate() { - ByteBuffer buffer = this.buffer; - if (buffer == null) { - return; - } - - this.buffer = null; - - if (!doNotFree) { - freeDirect(buffer); - } - } - - @Override - public ByteBuf unwrap() { - return null; - } - - long addr(int index) { - return memoryAddress + index; - } - - @Override - protected SwappedByteBuf newSwappedByteBuf() { - return new UnsafeDirectSwappedByteBuf(this); - } -} diff --git a/java/src/game/net/buffer/UnreleasableByteBuf.java b/java/src/game/net/buffer/UnreleasableByteBuf.java deleted file mode 100644 index 1d875a5..0000000 --- a/java/src/game/net/buffer/UnreleasableByteBuf.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.buffer; - -import java.nio.ByteOrder; - -/** - * A {@link ByteBuf} implementation that wraps another buffer to prevent a user from increasing or decreasing the - * wrapped buffer's reference count. - */ -final class UnreleasableByteBuf extends WrappedByteBuf { - - private SwappedByteBuf swappedBuf; - - UnreleasableByteBuf(ByteBuf buf) { - super(buf); - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order()) { - return this; - } - - SwappedByteBuf swappedBuf = this.swappedBuf; - if (swappedBuf == null) { - this.swappedBuf = swappedBuf = new SwappedByteBuf(this); - } - return swappedBuf; - } - - @Override - public ByteBuf readSlice(int length) { - return new UnreleasableByteBuf(buf.readSlice(length)); - } - - @Override - public ByteBuf slice() { - return new UnreleasableByteBuf(buf.slice()); - } - - @Override - public ByteBuf slice(int index, int length) { - return new UnreleasableByteBuf(buf.slice(index, length)); - } - - @Override - public ByteBuf duplicate() { - return new UnreleasableByteBuf(buf.duplicate()); - } - - @Override - public ByteBuf retain(int increment) { - return this; - } - - @Override - public ByteBuf retain() { - return this; - } - - @Override - public boolean release() { - return false; - } - - @Override - public boolean release(int decrement) { - return false; - } -} diff --git a/java/src/game/net/buffer/UnsafeDirectSwappedByteBuf.java b/java/src/game/net/buffer/UnsafeDirectSwappedByteBuf.java deleted file mode 100644 index e0ddcde..0000000 --- a/java/src/game/net/buffer/UnsafeDirectSwappedByteBuf.java +++ /dev/null @@ -1,186 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ - -package game.net.buffer; - -import java.nio.ByteOrder; - -import game.net.util.internal.PlatformDependent; - -/** - * Special {@link SwappedByteBuf} for {@link ByteBuf}s that are backed by a {@code memoryAddress}. - */ -final class UnsafeDirectSwappedByteBuf extends SwappedByteBuf { - private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - private final boolean nativeByteOrder; - private final AbstractByteBuf wrapped; - - UnsafeDirectSwappedByteBuf(AbstractByteBuf buf) { - super(buf); - wrapped = buf; - nativeByteOrder = NATIVE_ORDER == (order() == ByteOrder.BIG_ENDIAN); - } - - private long addr(int index) { - // We need to call wrapped.memoryAddress() everytime and NOT cache it as it may change if the buffer expand. - // See: - // - https://github.com/netty/netty/issues/2587 - // - https://github.com/netty/netty/issues/2580 - return wrapped.memoryAddress() + index; - } - - @Override - public long getLong(int index) { - wrapped.checkIndex(index, 8); - long v = PlatformDependent.getLong(addr(index)); - return nativeByteOrder? v : Long.reverseBytes(v); - } - - @Override - public float getFloat(int index) { - return Float.intBitsToFloat(getInt(index)); - } - - @Override - public double getDouble(int index) { - return Double.longBitsToDouble(getLong(index)); - } - - @Override - public char getChar(int index) { - return (char) getShort(index); - } - - @Override - public long getUnsignedInt(int index) { - return getInt(index) & 0xFFFFFFFFL; - } - - @Override - public int getInt(int index) { - wrapped.checkIndex(index, 4); - int v = PlatformDependent.getInt(addr(index)); - return nativeByteOrder? v : Integer.reverseBytes(v); - } - - @Override - public int getUnsignedShort(int index) { - return getShort(index) & 0xFFFF; - } - - @Override - public short getShort(int index) { - wrapped.checkIndex(index, 2); - short v = PlatformDependent.getShort(addr(index)); - return nativeByteOrder? v : Short.reverseBytes(v); - } - - @Override - public ByteBuf setShort(int index, int value) { - wrapped.checkIndex(index, 2); - _setShort(index, value); - return this; - } - - @Override - public ByteBuf setInt(int index, int value) { - wrapped.checkIndex(index, 4); - _setInt(index, value); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - wrapped.checkIndex(index, 8); - _setLong(index, value); - return this; - } - - @Override - public ByteBuf setChar(int index, int value) { - setShort(index, value); - return this; - } - - @Override - public ByteBuf setFloat(int index, float value) { - setInt(index, Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf setDouble(int index, double value) { - setLong(index, Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - wrapped.ensureAccessible(); - wrapped.ensureWritable(2); - _setShort(wrapped.writerIndex, value); - wrapped.writerIndex += 2; - return this; - } - - @Override - public ByteBuf writeInt(int value) { - wrapped.ensureAccessible(); - wrapped.ensureWritable(4); - _setInt(wrapped.writerIndex, value); - wrapped.writerIndex += 4; - return this; - } - - @Override - public ByteBuf writeLong(long value) { - wrapped.ensureAccessible(); - wrapped.ensureWritable(8); - _setLong(wrapped.writerIndex, value); - wrapped.writerIndex += 8; - return this; - } - - @Override - public ByteBuf writeChar(int value) { - writeShort(value); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - writeInt(Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - writeLong(Double.doubleToRawLongBits(value)); - return this; - } - - private void _setShort(int index, int value) { - PlatformDependent.putShort(addr(index), nativeByteOrder ? (short) value : Short.reverseBytes((short) value)); - } - - private void _setInt(int index, int value) { - PlatformDependent.putInt(addr(index), nativeByteOrder ? value : Integer.reverseBytes(value)); - } - - private void _setLong(int index, long value) { - PlatformDependent.putLong(addr(index), nativeByteOrder ? value : Long.reverseBytes(value)); - } -} diff --git a/java/src/game/net/buffer/WrappedByteBuf.java b/java/src/game/net/buffer/WrappedByteBuf.java deleted file mode 100644 index 2092fd7..0000000 --- a/java/src/game/net/buffer/WrappedByteBuf.java +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import game.net.util.internal.StringUtil; - -class WrappedByteBuf extends ByteBuf { - - protected final ByteBuf buf; - - protected WrappedByteBuf(ByteBuf buf) { - if (buf == null) { - throw new NullPointerException("buf"); - } - this.buf = buf; - } - - @Override - public boolean hasMemoryAddress() { - return buf.hasMemoryAddress(); - } - - @Override - public long memoryAddress() { - return buf.memoryAddress(); - } - - @Override - public int capacity() { - return buf.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - buf.capacity(newCapacity); - return this; - } - - @Override - public int maxCapacity() { - return buf.maxCapacity(); - } - - @Override - public ByteBufAllocator alloc() { - return buf.alloc(); - } - - @Override - public ByteOrder order() { - return buf.order(); - } - - @Override - public ByteBuf order(ByteOrder endianness) { - return buf.order(endianness); - } - - @Override - public ByteBuf unwrap() { - return buf; - } - - @Override - public boolean isDirect() { - return buf.isDirect(); - } - - @Override - public int readerIndex() { - return buf.readerIndex(); - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - buf.readerIndex(readerIndex); - return this; - } - - @Override - public int writerIndex() { - return buf.writerIndex(); - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - buf.writerIndex(writerIndex); - return this; - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - buf.setIndex(readerIndex, writerIndex); - return this; - } - - @Override - public int readableBytes() { - return buf.readableBytes(); - } - - @Override - public int writableBytes() { - return buf.writableBytes(); - } - - @Override - public int maxWritableBytes() { - return buf.maxWritableBytes(); - } - - @Override - public boolean isReadable() { - return buf.isReadable(); - } - - @Override - public boolean isWritable() { - return buf.isWritable(); - } - - @Override - public ByteBuf clear() { - buf.clear(); - return this; - } - - @Override - public ByteBuf markReaderIndex() { - buf.markReaderIndex(); - return this; - } - - @Override - public ByteBuf resetReaderIndex() { - buf.resetReaderIndex(); - return this; - } - - @Override - public ByteBuf markWriterIndex() { - buf.markWriterIndex(); - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - buf.resetWriterIndex(); - return this; - } - - @Override - public ByteBuf discardReadBytes() { - buf.discardReadBytes(); - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - buf.discardSomeReadBytes(); - return this; - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - buf.ensureWritable(minWritableBytes); - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - return buf.ensureWritable(minWritableBytes, force); - } - - @Override - public boolean getBoolean(int index) { - return buf.getBoolean(index); - } - - @Override - public byte getByte(int index) { - return buf.getByte(index); - } - - @Override - public short getUnsignedByte(int index) { - return buf.getUnsignedByte(index); - } - - @Override - public short getShort(int index) { - return buf.getShort(index); - } - - @Override - public int getUnsignedShort(int index) { - return buf.getUnsignedShort(index); - } - - @Override - public int getMedium(int index) { - return buf.getMedium(index); - } - - @Override - public int getUnsignedMedium(int index) { - return buf.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - return buf.getInt(index); - } - - @Override - public long getUnsignedInt(int index) { - return buf.getUnsignedInt(index); - } - - @Override - public long getLong(int index) { - return buf.getLong(index); - } - - @Override - public char getChar(int index) { - return buf.getChar(index); - } - - @Override - public float getFloat(int index) { - return buf.getFloat(index); - } - - @Override - public double getDouble(int index) { - return buf.getDouble(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - buf.getBytes(index, dst, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - buf.getBytes(index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return buf.getBytes(index, out, length); - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - buf.setBoolean(index, value); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - buf.setByte(index, value); - return this; - } - - @Override - public ByteBuf setShort(int index, int value) { - buf.setShort(index, value); - return this; - } - - @Override - public ByteBuf setMedium(int index, int value) { - buf.setMedium(index, value); - return this; - } - - @Override - public ByteBuf setInt(int index, int value) { - buf.setInt(index, value); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - buf.setLong(index, value); - return this; - } - - @Override - public ByteBuf setChar(int index, int value) { - buf.setChar(index, value); - return this; - } - - @Override - public ByteBuf setFloat(int index, float value) { - buf.setFloat(index, value); - return this; - } - - @Override - public ByteBuf setDouble(int index, double value) { - buf.setDouble(index, value); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - buf.setBytes(index, src, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - buf.setBytes(index, src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public ByteBuf setZero(int index, int length) { - buf.setZero(index, length); - return this; - } - - @Override - public boolean readBoolean() { - return buf.readBoolean(); - } - - @Override - public byte readByte() { - return buf.readByte(); - } - - @Override - public short readUnsignedByte() { - return buf.readUnsignedByte(); - } - - @Override - public short readShort() { - return buf.readShort(); - } - - @Override - public int readUnsignedShort() { - return buf.readUnsignedShort(); - } - - @Override - public int readMedium() { - return buf.readMedium(); - } - - @Override - public int readUnsignedMedium() { - return buf.readUnsignedMedium(); - } - - @Override - public int readInt() { - return buf.readInt(); - } - - @Override - public long readUnsignedInt() { - return buf.readUnsignedInt(); - } - - @Override - public long readLong() { - return buf.readLong(); - } - - @Override - public char readChar() { - return buf.readChar(); - } - - @Override - public float readFloat() { - return buf.readFloat(); - } - - @Override - public double readDouble() { - return buf.readDouble(); - } - - @Override - public ByteBuf readBytes(int length) { - return buf.readBytes(length); - } - - @Override - public ByteBuf readSlice(int length) { - return buf.readSlice(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - buf.readBytes(dst, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - buf.readBytes(out, length); - return this; - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - return buf.readBytes(out, length); - } - - @Override - public ByteBuf skipBytes(int length) { - buf.skipBytes(length); - return this; - } - - @Override - public ByteBuf writeBoolean(boolean value) { - buf.writeBoolean(value); - return this; - } - - @Override - public ByteBuf writeByte(int value) { - buf.writeByte(value); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - buf.writeShort(value); - return this; - } - - @Override - public ByteBuf writeMedium(int value) { - buf.writeMedium(value); - return this; - } - - @Override - public ByteBuf writeInt(int value) { - buf.writeInt(value); - return this; - } - - @Override - public ByteBuf writeLong(long value) { - buf.writeLong(value); - return this; - } - - @Override - public ByteBuf writeChar(int value) { - buf.writeChar(value); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - buf.writeFloat(value); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - buf.writeDouble(value); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - buf.writeBytes(src, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - buf.writeBytes(src); - return this; - } - - @Override - public int writeBytes(InputStream in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public ByteBuf writeZero(int length) { - buf.writeZero(length); - return this; - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - return buf.indexOf(fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - return buf.bytesBefore(value); - } - - @Override - public int bytesBefore(int length, byte value) { - return buf.bytesBefore(length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - return buf.bytesBefore(index, length, value); - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - return buf.forEachByte(processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buf.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - return buf.forEachByteDesc(processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buf.forEachByteDesc(index, length, processor); - } - - @Override - public ByteBuf copy() { - return buf.copy(); - } - - @Override - public ByteBuf copy(int index, int length) { - return buf.copy(index, length); - } - - @Override - public ByteBuf slice() { - return buf.slice(); - } - - @Override - public ByteBuf slice(int index, int length) { - return buf.slice(index, length); - } - - @Override - public ByteBuf duplicate() { - return buf.duplicate(); - } - - @Override - public int nioBufferCount() { - return buf.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer() { - return buf.nioBuffer(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return buf.nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers() { - return buf.nioBuffers(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return buf.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return buf.internalNioBuffer(index, length); - } - - @Override - public boolean hasArray() { - return buf.hasArray(); - } - - @Override - public byte[] array() { - return buf.array(); - } - - @Override - public int arrayOffset() { - return buf.arrayOffset(); - } - - @Override - public String toString(Charset charset) { - return buf.toString(charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - return buf.toString(index, length, charset); - } - - @Override - public int hashCode() { - return buf.hashCode(); - } - - @Override - - public boolean equals(Object obj) { - return buf.equals(obj); - } - - @Override - public int compareTo(ByteBuf buffer) { - return buf.compareTo(buffer); - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + '(' + buf.toString() + ')'; - } - - @Override - public ByteBuf retain(int increment) { - buf.retain(increment); - return this; - } - - @Override - public ByteBuf retain() { - buf.retain(); - return this; - } - - @Override - public boolean isReadable(int size) { - return buf.isReadable(size); - } - - @Override - public boolean isWritable(int size) { - return buf.isWritable(size); - } - - @Override - public int refCnt() { - return buf.refCnt(); - } - - @Override - public boolean release() { - return buf.release(); - } - - @Override - public boolean release(int decrement) { - return buf.release(decrement); - } -} diff --git a/java/src/game/net/channel/AbstractChannel.java b/java/src/game/net/channel/AbstractChannel.java deleted file mode 100644 index a2c2578..0000000 --- a/java/src/game/net/channel/AbstractChannel.java +++ /dev/null @@ -1,873 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NotYetConnectedException; -import java.util.concurrent.RejectedExecutionException; - -import game.net.buffer.ByteBufAllocator; -import game.net.util.DefaultAttributeMap; -import game.net.util.ReferenceCountUtil; -import game.net.util.internal.EmptyArrays; -import game.net.util.internal.OneTimeTask; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.ThreadLocalRandom; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A skeletal {@link Channel} implementation. - */ -public abstract class AbstractChannel extends DefaultAttributeMap implements Channel { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class); - - static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - static final NotYetConnectedException NOT_YET_CONNECTED_EXCEPTION = new NotYetConnectedException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - NOT_YET_CONNECTED_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - private MessageSizeEstimator.Handle estimatorHandle; - - private final Channel parent; - private final long hashCode = ThreadLocalRandom.current().nextLong(); - private final Unsafe unsafe; - private final DefaultChannelPipeline pipeline; - private final ChannelFuture succeededFuture = new SucceededChannelFuture(this, null); - private final VoidChannelPromise voidPromise = new VoidChannelPromise(this, true); - private final VoidChannelPromise unsafeVoidPromise = new VoidChannelPromise(this, false); - private final CloseFuture closeFuture = new CloseFuture(this); - - private volatile SocketAddress localAddress; - private volatile SocketAddress remoteAddress; - private volatile EventLoop eventLoop; - private volatile boolean registered; - - /** Cache for the string representation of this channel */ - private boolean strValActive; - private String strVal; - - /** - * Creates a new instance. - * - * @param parent - * the parent of this channel. {@code null} if there's no parent. - */ - protected AbstractChannel(Channel parent) { - this.parent = parent; - unsafe = newUnsafe(); - pipeline = new DefaultChannelPipeline(this); - } - - @Override - public boolean isWritable() { - ChannelOutboundBuffer buf = unsafe.outboundBuffer(); - return buf != null && buf.isWritable(); - } - - @Override - public Channel parent() { - return parent; - } - - @Override - public ChannelPipeline pipeline() { - return pipeline; - } - - @Override - public ByteBufAllocator alloc() { - return config().getAllocator(); - } - - @Override - public EventLoop eventLoop() { - EventLoop eventLoop = this.eventLoop; - if (eventLoop == null) { - throw new IllegalStateException("channel not registered to an event loop"); - } - return eventLoop; - } - - @Override - public SocketAddress localAddress() { - SocketAddress localAddress = this.localAddress; - if (localAddress == null) { - try { - this.localAddress = localAddress = unsafe().localAddress(); - } catch (Throwable t) { - // Sometimes fails on a closed socket in Windows. - return null; - } - } - return localAddress; - } - - protected void invalidateLocalAddress() { - localAddress = null; - } - - @Override - public SocketAddress remoteAddress() { - SocketAddress remoteAddress = this.remoteAddress; - if (remoteAddress == null) { - try { - this.remoteAddress = remoteAddress = unsafe().remoteAddress(); - } catch (Throwable t) { - // Sometimes fails on a closed socket in Windows. - return null; - } - } - return remoteAddress; - } - - /** - * Reset the stored remoteAddress - */ - protected void invalidateRemoteAddress() { - remoteAddress = null; - } - - @Override - public boolean isRegistered() { - return registered; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress) { - return pipeline.bind(localAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress) { - return pipeline.connect(remoteAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - return pipeline.connect(remoteAddress, localAddress); - } - - @Override - public ChannelFuture disconnect() { - return pipeline.disconnect(); - } - - @Override - public ChannelFuture close() { - return pipeline.close(); - } - - @Override - public ChannelFuture deregister() { - return pipeline.deregister(); - } - - @Override - public Channel flush() { - pipeline.flush(); - return this; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { - return pipeline.bind(localAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { - return pipeline.connect(remoteAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - return pipeline.connect(remoteAddress, localAddress, promise); - } - - @Override - public ChannelFuture disconnect(ChannelPromise promise) { - return pipeline.disconnect(promise); - } - - @Override - public ChannelFuture close(ChannelPromise promise) { - return pipeline.close(promise); - } - - @Override - public ChannelFuture deregister(ChannelPromise promise) { - return pipeline.deregister(promise); - } - - @Override - public Channel read() { - pipeline.read(); - return this; - } - - @Override - public ChannelFuture write(Object msg) { - return pipeline.write(msg); - } - - @Override - public ChannelFuture write(Object msg, ChannelPromise promise) { - return pipeline.write(msg, promise); - } - - @Override - public ChannelFuture writeAndFlush(Object msg) { - return pipeline.writeAndFlush(msg); - } - - @Override - public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { - return pipeline.writeAndFlush(msg, promise); - } - - @Override - public ChannelPromise newPromise() { - return new DefaultChannelPromise(this); - } - -// @Override -// public ChannelProgressivePromise newProgressivePromise() { -// return new DefaultChannelProgressivePromise(this); -// } - - @Override - public ChannelFuture newSucceededFuture() { - return succeededFuture; - } - - @Override - public ChannelFuture newFailedFuture(Throwable cause) { - return new FailedChannelFuture(this, null, cause); - } - - @Override - public ChannelFuture closeFuture() { - return closeFuture; - } - - @Override - public Unsafe unsafe() { - return unsafe; - } - - /** - * Create a new {@link AbstractUnsafe} instance which will be used for the life-time of the {@link Channel} - */ - protected abstract AbstractUnsafe newUnsafe(); - - /** - * Returns the ID of this channel. - */ - @Override - public final int hashCode() { - return (int) hashCode; - } - - /** - * Returns {@code true} if and only if the specified object is identical - * with this channel (i.e: {@code this == o}). - */ - @Override - public final boolean equals(Object o) { - return this == o; - } - - @Override - public final int compareTo(Channel o) { - if (this == o) { - return 0; - } - - long ret = hashCode - o.hashCode(); - if (ret > 0) { - return 1; - } - if (ret < 0) { - return -1; - } - - ret = System.identityHashCode(this) - System.identityHashCode(o); - if (ret != 0) { - return (int) ret; - } - - // Jackpot! - different objects with same hashes - throw new Error(); - } - - /** - * Returns the {@link String} representation of this channel. The returned - * string contains the {@linkplain #hashCode()} ID}, {@linkplain #localAddress() local address}, - * and {@linkplain #remoteAddress() remote address} of this channel for - * easier identification. - */ - @Override - public String toString() { - boolean active = isActive(); - if (strValActive == active && strVal != null) { - return strVal; - } - - SocketAddress remoteAddr = remoteAddress(); - SocketAddress localAddr = localAddress(); - if (remoteAddr != null) { - SocketAddress srcAddr; - SocketAddress dstAddr; - if (parent == null) { - srcAddr = localAddr; - dstAddr = remoteAddr; - } else { - srcAddr = remoteAddr; - dstAddr = localAddr; - } - strVal = String.format("[id: 0x%08x, %s %s %s]", (int) hashCode, srcAddr, active? "=>" : ":>", dstAddr); - } else if (localAddr != null) { - strVal = String.format("[id: 0x%08x, %s]", (int) hashCode, localAddr); - } else { - strVal = String.format("[id: 0x%08x]", (int) hashCode); - } - - strValActive = active; - return strVal; - } - - @Override - public final ChannelPromise voidPromise() { - return voidPromise; - } - - final MessageSizeEstimator.Handle estimatorHandle() { - if (estimatorHandle == null) { - estimatorHandle = config().getMessageSizeEstimator().newHandle(); - } - return estimatorHandle; - } - - /** - * {@link Unsafe} implementation which sub-classes must extend and use. - */ - protected abstract class AbstractUnsafe implements Unsafe { - - private ChannelOutboundBuffer outboundBuffer = new ChannelOutboundBuffer(AbstractChannel.this); - private boolean inFlush0; - - @Override - public final ChannelOutboundBuffer outboundBuffer() { - return outboundBuffer; - } - - @Override - public final SocketAddress localAddress() { - return localAddress0(); - } - - @Override - public final SocketAddress remoteAddress() { - return remoteAddress0(); - } - - @Override - public final void register(EventLoop eventLoop, final ChannelPromise promise) { - if (eventLoop == null) { - throw new NullPointerException("eventLoop"); - } - if (isRegistered()) { - promise.setFailure(new IllegalStateException("registered to an event loop already")); - return; - } - if (!isCompatible(eventLoop)) { - promise.setFailure( - new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName())); - return; - } - - AbstractChannel.this.eventLoop = eventLoop; - - if (eventLoop.inEventLoop()) { - register0(promise); - } else { - try { - eventLoop.execute(new OneTimeTask() { - @Override - public void run() { - register0(promise); - } - }); - } catch (Throwable t) { - logger.warn( - "Force-closing a channel whose registration task was not accepted by an event loop: {}", - AbstractChannel.this, t); - closeForcibly(); - closeFuture.setClosed(); - safeSetFailure(promise, t); - } - } - } - - private void register0(ChannelPromise promise) { - try { - // check if the channel is still open as it could be closed in the mean time when the register - // call was outside of the eventLoop - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - doRegister(); - registered = true; - safeSetSuccess(promise); - pipeline.fireChannelRegistered(); - if (isActive()) { - pipeline.fireChannelActive(); - } - } catch (Throwable t) { - // Close the channel directly to avoid FD leak. - closeForcibly(); - closeFuture.setClosed(); - safeSetFailure(promise, t); - } - } - - @Override - public final void bind(final SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - // See: https://github.com/netty/netty/issues/576 - if (!PlatformDependent.isWindows() && !PlatformDependent.isRoot() && - Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) && - localAddress instanceof InetSocketAddress && - !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress()) { - // Warn a user about the fact that a non-root user can't receive a - // broadcast packet on *nix if the socket is bound on non-wildcard address. - logger.warn( - "A non-root user can't receive a broadcast packet if the socket " + - "is not bound to a wildcard address; binding to a non-wildcard " + - "address (" + localAddress + ") anyway as requested."); - } - - boolean wasActive = isActive(); - try { - doBind(localAddress); - } catch (Throwable t) { - safeSetFailure(promise, t); - closeIfClosed(); - return; - } - - if (!wasActive && isActive()) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelActive(); - } - }); - } - - safeSetSuccess(promise); - } - - @Override - public final void disconnect(final ChannelPromise promise) { - if (!promise.setUncancellable()) { - return; - } - - boolean wasActive = isActive(); - try { - doDisconnect(); - } catch (Throwable t) { - safeSetFailure(promise, t); - closeIfClosed(); - return; - } - - if (wasActive && !isActive()) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelInactive(); - } - }); - } - - safeSetSuccess(promise); - closeIfClosed(); // doDisconnect() might have closed the channel - } - - @Override - public final void close(final ChannelPromise promise) { - if (!promise.setUncancellable()) { - return; - } - - if (inFlush0) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - close(promise); - } - }); - return; - } - - if (closeFuture.isDone()) { - // Closed already. - safeSetSuccess(promise); - return; - } - - boolean wasActive = isActive(); - ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer. - - try { - doClose(); - closeFuture.setClosed(); - safeSetSuccess(promise); - } catch (Throwable t) { - closeFuture.setClosed(); - safeSetFailure(promise, t); - } - - // Fail all the queued messages - try { - outboundBuffer.failFlushed(CLOSED_CHANNEL_EXCEPTION); - outboundBuffer.close(CLOSED_CHANNEL_EXCEPTION); - } finally { - - if (wasActive && !isActive()) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelInactive(); - } - }); - } - - deregister(voidPromise()); - } - } - - @Override - public final void closeForcibly() { - try { - doClose(); - } catch (Exception e) { - logger.warn("Failed to close a channel.", e); - } - } - - @Override - public final void deregister(final ChannelPromise promise) { - if (!promise.setUncancellable()) { - return; - } - - if (!registered) { - safeSetSuccess(promise); - return; - } - - try { - doDeregister(); - } catch (Throwable t) { - logger.warn("Unexpected exception occurred while deregistering a channel.", t); - } finally { - if (registered) { - registered = false; - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelUnregistered(); - } - }); - safeSetSuccess(promise); - } else { - // Some transports like local and AIO does not allow the deregistration of - // an open channel. Their doDeregister() calls close(). Consequently, - // close() calls deregister() again - no need to fire channelUnregistered. - safeSetSuccess(promise); - } - } - } - - @Override - public final void beginRead() { - if (!isActive()) { - return; - } - - try { - doBeginRead(); - } catch (final Exception e) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireExceptionCaught(e); - } - }); - close(voidPromise()); - } - } - - @Override - public final void write(Object msg, ChannelPromise promise) { - ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - if (outboundBuffer == null) { - // If the outboundBuffer is null we know the channel was closed and so - // need to fail the future right away. If it is not null the handling of the rest - // will be done in flush0() - // See https://github.com/netty/netty/issues/2362 - safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION); - // release message now to prevent resource-leak - ReferenceCountUtil.release(msg); - return; - } - - int size; - try { - msg = filterOutboundMessage(msg); - size = estimatorHandle().size(msg); - if (size < 0) { - size = 0; - } - } catch (Throwable t) { - safeSetFailure(promise, t); - ReferenceCountUtil.release(msg); - return; - } - - outboundBuffer.addMessage(msg, size, promise); - } - - @Override - public final void flush() { - ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - if (outboundBuffer == null) { - return; - } - - outboundBuffer.addFlush(); - flush0(); - } - - protected void flush0() { - if (inFlush0) { - // Avoid re-entrance - return; - } - - final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - if (outboundBuffer == null || outboundBuffer.isEmpty()) { - return; - } - - inFlush0 = true; - - // Mark all pending write requests as failure if the channel is inactive. - if (!isActive()) { - try { - if (isOpen()) { - outboundBuffer.failFlushed(NOT_YET_CONNECTED_EXCEPTION); - } else { - outboundBuffer.failFlushed(CLOSED_CHANNEL_EXCEPTION); - } - } finally { - inFlush0 = false; - } - return; - } - - try { - doWrite(outboundBuffer); - } catch (Throwable t) { - outboundBuffer.failFlushed(t); - if (t instanceof IOException && config().isAutoClose()) { - close(voidPromise()); - } - } finally { - inFlush0 = false; - } - } - - @Override - public final ChannelPromise voidPromise() { - return unsafeVoidPromise; - } - - protected final boolean ensureOpen(ChannelPromise promise) { - if (isOpen()) { - return true; - } - - safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION); - return false; - } - - /** - * Marks the specified {@code promise} as success. If the {@code promise} is done already, log a message. - */ - protected final void safeSetSuccess(ChannelPromise promise) { - if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) { - logger.warn("Failed to mark a promise as success because it is done already: {}", promise); - } - } - - /** - * Marks the specified {@code promise} as failure. If the {@code promise} is done already, log a message. - */ - protected final void safeSetFailure(ChannelPromise promise, Throwable cause) { - if (!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) { - logger.warn("Failed to mark a promise as failure because it's done already: {}", promise, cause); - } - } - - protected final void closeIfClosed() { - if (isOpen()) { - return; - } - close(voidPromise()); - } - - private void invokeLater(Runnable task) { - try { - // This method is used by outbound operation implementations to trigger an inbound event later. - // They do not trigger an inbound event immediately because an outbound operation might have been - // triggered by another inbound event handler method. If fired immediately, the call stack - // will look like this for example: - // - // handlerA.inboundBufferUpdated() - (1) an inbound handler method closes a connection. - // -> handlerA.ctx.close() - // -> channel.unsafe.close() - // -> handlerA.channelInactive() - (2) another inbound handler method called while in (1) yet - // - // which means the execution of two inbound handler methods of the same handler overlap undesirably. - eventLoop().execute(task); - } catch (RejectedExecutionException e) { - logger.warn("Can't invoke task later as EventLoop rejected it", e); - } - } - } - - /** - * Return {@code true} if the given {@link EventLoop} is compatible with this instance. - */ - protected abstract boolean isCompatible(EventLoop loop); - - /** - * Returns the {@link SocketAddress} which is bound locally. - */ - protected abstract SocketAddress localAddress0(); - - /** - * Return the {@link SocketAddress} which the {@link Channel} is connected to. - */ - protected abstract SocketAddress remoteAddress0(); - - /** - * Is called after the {@link Channel} is registered with its {@link EventLoop} as part of the register process. - * - * Sub-classes may override this method - */ - protected void doRegister() throws Exception { - // NOOP - } - - /** - * Bind the {@link Channel} to the {@link SocketAddress} - */ - protected abstract void doBind(SocketAddress localAddress) throws Exception; - - /** - * Disconnect this {@link Channel} from its remote peer - */ - protected abstract void doDisconnect() throws Exception; - - /** - * Close the {@link Channel} - */ - protected abstract void doClose() throws Exception; - - /** - * Deregister the {@link Channel} from its {@link EventLoop}. - * - * Sub-classes may override this method - */ - protected void doDeregister() throws Exception { - // NOOP - } - - /** - * Schedule a read operation. - */ - protected abstract void doBeginRead() throws Exception; - - /** - * Flush the content of the given buffer to the remote peer. - */ - protected abstract void doWrite(ChannelOutboundBuffer in) throws Exception; - - /** - * Invoked when a new message is added to a {@link ChannelOutboundBuffer} of this {@link AbstractChannel}, so that - * the {@link Channel} implementation converts the message to another. (e.g. heap buffer -> direct buffer) - */ - protected Object filterOutboundMessage(Object msg) throws Exception { - return msg; - } - - static final class CloseFuture extends DefaultChannelPromise { - - CloseFuture(AbstractChannel ch) { - super(ch); - } - - @Override - public ChannelPromise setSuccess() { - throw new IllegalStateException(); - } - - @Override - public ChannelPromise setFailure(Throwable cause) { - throw new IllegalStateException(); - } - - @Override - public boolean trySuccess() { - throw new IllegalStateException(); - } - - @Override - public boolean tryFailure(Throwable cause) { - throw new IllegalStateException(); - } - - boolean setClosed() { - return super.trySuccess(); - } - } -} diff --git a/java/src/game/net/channel/AbstractChannelHandlerContext.java b/java/src/game/net/channel/AbstractChannelHandlerContext.java deleted file mode 100644 index dcaf73b..0000000 --- a/java/src/game/net/channel/AbstractChannelHandlerContext.java +++ /dev/null @@ -1,1000 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import static game.net.channel.DefaultChannelPipeline.logger; - -import java.net.SocketAddress; - -import game.net.buffer.ByteBufAllocator; -import game.net.util.DefaultAttributeMap; -import game.net.util.Recycler; -import game.net.util.ReferenceCountUtil; -import game.net.util.concurrent.EventExecutor; -import game.net.util.concurrent.EventExecutorGroup; -import game.net.util.internal.OneTimeTask; -import game.net.util.internal.RecyclableMpscLinkedQueueNode; -import game.net.util.internal.StringUtil; - -abstract class AbstractChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext { - - volatile AbstractChannelHandlerContext next; - volatile AbstractChannelHandlerContext prev; - - private final boolean inbound; - private final boolean outbound; - private final AbstractChannel channel; - private final DefaultChannelPipeline pipeline; - private final String name; - private boolean removed; - - // Will be set to null if no child executor should be used, otherwise it will be set to the - // child executor. - final EventExecutor executor; - private ChannelFuture succeededFuture; - - // Lazily instantiated tasks used to trigger events to a handler with different executor. - // These needs to be volatile as otherwise an other Thread may see an half initialized instance. - // See the JMM for more details - private volatile Runnable invokeChannelReadCompleteTask; - private volatile Runnable invokeReadTask; - private volatile Runnable invokeChannelWritableStateChangedTask; - private volatile Runnable invokeFlushTask; - - AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutorGroup group, String name, - boolean inbound, boolean outbound) { - - if (name == null) { - throw new NullPointerException("name"); - } - - channel = pipeline.channel; - this.pipeline = pipeline; - this.name = name; - - if (group != null) { - // Pin one of the child executors once and remember it so that the same child executor - // is used to fire events for the same channel. - EventExecutor childExecutor = pipeline.childExecutors.get(group); - if (childExecutor == null) { - childExecutor = group.next(); - pipeline.childExecutors.put(group, childExecutor); - } - executor = childExecutor; - } else { - executor = null; - } - - this.inbound = inbound; - this.outbound = outbound; - } - - /** Invocation initiated by {@link DefaultChannelPipeline#teardownAll()}}. */ - void teardown() { - EventExecutor executor = executor(); - if (executor.inEventLoop()) { - teardown0(); - } else { - executor.execute(new Runnable() { - @Override - public void run() { - teardown0(); - } - }); - } - } - - private void teardown0() { - AbstractChannelHandlerContext prev = this.prev; - if (prev != null) { - synchronized (pipeline) { - pipeline.remove0(this); - } - prev.teardown(); - } - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelPipeline pipeline() { - return pipeline; - } - - @Override - public ByteBufAllocator alloc() { - return channel().config().getAllocator(); - } - - @Override - public EventExecutor executor() { - if (executor == null) { - return channel().eventLoop(); - } else { - return executor; - } - } - - @Override - public String name() { - return name; - } - - @Override - public ChannelHandlerContext fireChannelRegistered() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelRegistered(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelRegistered(); - } - }); - } - return this; - } - - private void invokeChannelRegistered() { - try { - ((ChannelInboundHandler) handler()).channelRegistered(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelUnregistered() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelUnregistered(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelUnregistered(); - } - }); - } - return this; - } - - private void invokeChannelUnregistered() { - try { - ((ChannelInboundHandler) handler()).channelUnregistered(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelActive() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelActive(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelActive(); - } - }); - } - return this; - } - - private void invokeChannelActive() { - try { - ((ChannelInboundHandler) handler()).channelActive(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelInactive() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelInactive(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelInactive(); - } - }); - } - return this; - } - - private void invokeChannelInactive() { - try { - ((ChannelInboundHandler) handler()).channelInactive(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireExceptionCaught(final Throwable cause) { - if (cause == null) { - throw new NullPointerException("cause"); - } - - final AbstractChannelHandlerContext next = this.next; - - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeExceptionCaught(cause); - } else { - try { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeExceptionCaught(cause); - } - }); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to submit an exceptionCaught() event.", t); - logger.warn("The exceptionCaught() event that was failed to submit was:", cause); - } - } - } - - return this; - } - - private void invokeExceptionCaught(final Throwable cause) { - try { - handler().exceptionCaught(this, cause); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn( - "An exception was thrown by a user handler's " + - "exceptionCaught() method while handling the following exception:", cause); - } - } - } - - @Override - public ChannelHandlerContext fireUserEventTriggered(final Object event) { - if (event == null) { - throw new NullPointerException("event"); - } - - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeUserEventTriggered(event); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeUserEventTriggered(event); - } - }); - } - return this; - } - - private void invokeUserEventTriggered(Object event) { - try { - ((ChannelInboundHandler) handler()).userEventTriggered(this, event); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelRead(final Object msg) { - if (msg == null) { - throw new NullPointerException("msg"); - } - - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelRead(msg); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelRead(msg); - } - }); - } - return this; - } - - private void invokeChannelRead(Object msg) { - try { - ((ChannelInboundHandler) handler()).channelRead(this, msg); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelReadComplete() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelReadComplete(); - } else { - Runnable task = next.invokeChannelReadCompleteTask; - if (task == null) { - next.invokeChannelReadCompleteTask = task = new Runnable() { - @Override - public void run() { - next.invokeChannelReadComplete(); - } - }; - } - executor.execute(task); - } - return this; - } - - private void invokeChannelReadComplete() { - try { - ((ChannelInboundHandler) handler()).channelReadComplete(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelWritabilityChanged() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelWritabilityChanged(); - } else { - Runnable task = next.invokeChannelWritableStateChangedTask; - if (task == null) { - next.invokeChannelWritableStateChangedTask = task = new Runnable() { - @Override - public void run() { - next.invokeChannelWritabilityChanged(); - } - }; - } - executor.execute(task); - } - return this; - } - - private void invokeChannelWritabilityChanged() { - try { - ((ChannelInboundHandler) handler()).channelWritabilityChanged(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelFuture bind(SocketAddress localAddress) { - return bind(localAddress, newPromise()); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress) { - return connect(remoteAddress, newPromise()); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - return connect(remoteAddress, localAddress, newPromise()); - } - - @Override - public ChannelFuture disconnect() { - return disconnect(newPromise()); - } - - @Override - public ChannelFuture close() { - return close(newPromise()); - } - - @Override - public ChannelFuture deregister() { - return deregister(newPromise()); - } - - @Override - public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) { - if (localAddress == null) { - throw new NullPointerException("localAddress"); - } - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeBind(localAddress, promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeBind(localAddress, promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeBind(SocketAddress localAddress, ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).bind(this, localAddress, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { - return connect(remoteAddress, null, promise); - } - - @Override - public ChannelFuture connect( - final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { - - if (remoteAddress == null) { - throw new NullPointerException("remoteAddress"); - } - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeConnect(remoteAddress, localAddress, promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeConnect(remoteAddress, localAddress, promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeConnect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).connect(this, remoteAddress, localAddress, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture disconnect(final ChannelPromise promise) { - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - // Translate disconnect to close if the channel has no notion of disconnect-reconnect. - // So far, UDP/IP is the only transport that has such behavior. - if (!channel().metadata().hasDisconnect()) { - next.invokeClose(promise); - } else { - next.invokeDisconnect(promise); - } - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - if (!channel().metadata().hasDisconnect()) { - next.invokeClose(promise); - } else { - next.invokeDisconnect(promise); - } - } - }, promise, null); - } - - return promise; - } - - private void invokeDisconnect(ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).disconnect(this, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture close(final ChannelPromise promise) { - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeClose(promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeClose(promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeClose(ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).close(this, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture deregister(final ChannelPromise promise) { - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeDeregister(promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeDeregister(promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeDeregister(ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).deregister(this, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelHandlerContext read() { - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeRead(); - } else { - Runnable task = next.invokeReadTask; - if (task == null) { - next.invokeReadTask = task = new Runnable() { - @Override - public void run() { - next.invokeRead(); - } - }; - } - executor.execute(task); - } - - return this; - } - - private void invokeRead() { - try { - ((ChannelOutboundHandler) handler()).read(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelFuture write(Object msg) { - return write(msg, newPromise()); - } - - @Override - public ChannelFuture write(final Object msg, final ChannelPromise promise) { - if (msg == null) { - throw new NullPointerException("msg"); - } - - if (!validatePromise(promise, true)) { - ReferenceCountUtil.release(msg); - // cancelled - return promise; - } - write(msg, false, promise); - - return promise; - } - - private void invokeWrite(Object msg, ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).write(this, msg, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelHandlerContext flush() { - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeFlush(); - } else { - Runnable task = next.invokeFlushTask; - if (task == null) { - next.invokeFlushTask = task = new Runnable() { - @Override - public void run() { - next.invokeFlush(); - } - }; - } - safeExecute(executor, task, channel.voidPromise(), null); - } - - return this; - } - - private void invokeFlush() { - try { - ((ChannelOutboundHandler) handler()).flush(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { - if (msg == null) { - throw new NullPointerException("msg"); - } - - if (!validatePromise(promise, true)) { - ReferenceCountUtil.release(msg); - // cancelled - return promise; - } - - write(msg, true, promise); - - return promise; - } - - private void write(Object msg, boolean flush, ChannelPromise promise) { - - AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeWrite(msg, promise); - if (flush) { - next.invokeFlush(); - } - } else { - int size = channel.estimatorHandle().size(msg); - if (size > 0) { - ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer(); - // Check for null as it may be set to null if the channel is closed already - if (buffer != null) { - buffer.incrementPendingOutboundBytes(size); - } - } - Runnable task; - if (flush) { - task = WriteAndFlushTask.newInstance(next, msg, size, promise); - } else { - task = WriteTask.newInstance(next, msg, size, promise); - } - safeExecute(executor, task, promise, msg); - } - } - - @Override - public ChannelFuture writeAndFlush(Object msg) { - return writeAndFlush(msg, newPromise()); - } - - private static void notifyOutboundHandlerException(Throwable cause, ChannelPromise promise) { - // only try to fail the promise if its not a VoidChannelPromise, as - // the VoidChannelPromise would also fire the cause through the pipeline - if (promise instanceof VoidChannelPromise) { - return; - } - - if (!promise.tryFailure(cause)) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to fail the promise because it's done already: {}", promise, cause); - } - } - } - - private void notifyHandlerException(Throwable cause) { - if (inExceptionCaught(cause)) { - if (logger.isWarnEnabled()) { - logger.warn( - "An exception was thrown by a user handler " + - "while handling an exceptionCaught event", cause); - } - return; - } - - invokeExceptionCaught(cause); - } - - private static boolean inExceptionCaught(Throwable cause) { - do { - StackTraceElement[] trace = cause.getStackTrace(); - if (trace != null) { - for (StackTraceElement t : trace) { - if (t == null) { - break; - } - if ("exceptionCaught".equals(t.getMethodName())) { - return true; - } - } - } - - cause = cause.getCause(); - } while (cause != null); - - return false; - } - - @Override - public ChannelPromise newPromise() { - return new DefaultChannelPromise(channel(), executor()); - } - -// @Override -// public ChannelProgressivePromise newProgressivePromise() { -// return new DefaultChannelProgressivePromise(channel(), executor()); -// } - - @Override - public ChannelFuture newSucceededFuture() { - ChannelFuture succeededFuture = this.succeededFuture; - if (succeededFuture == null) { - this.succeededFuture = succeededFuture = new SucceededChannelFuture(channel(), executor()); - } - return succeededFuture; - } - - @Override - public ChannelFuture newFailedFuture(Throwable cause) { - return new FailedChannelFuture(channel(), executor(), cause); - } - - private boolean validatePromise(ChannelPromise promise, boolean allowVoidPromise) { - if (promise == null) { - throw new NullPointerException("promise"); - } - - if (promise.isDone()) { - // Check if the promise was cancelled and if so signal that the processing of the operation - // should not be performed. - // - // See https://github.com/netty/netty/issues/2349 - if (promise.isCancelled()) { - return false; - } - throw new IllegalArgumentException("promise already done: " + promise); - } - - if (promise.channel() != channel()) { - throw new IllegalArgumentException(String.format( - "promise.channel does not match: %s (expected: %s)", promise.channel(), channel())); - } - - if (promise.getClass() == DefaultChannelPromise.class) { - return true; - } - - if (!allowVoidPromise && promise instanceof VoidChannelPromise) { - throw new IllegalArgumentException( - StringUtil.simpleClassName(VoidChannelPromise.class) + " not allowed for this operation"); - } - - if (promise instanceof AbstractChannel.CloseFuture) { - throw new IllegalArgumentException( - StringUtil.simpleClassName(AbstractChannel.CloseFuture.class) + " not allowed in a pipeline"); - } - return true; - } - - private AbstractChannelHandlerContext findContextInbound() { - AbstractChannelHandlerContext ctx = this; - do { - ctx = ctx.next; - } while (!ctx.inbound); - return ctx; - } - - private AbstractChannelHandlerContext findContextOutbound() { - AbstractChannelHandlerContext ctx = this; - do { - ctx = ctx.prev; - } while (!ctx.outbound); - return ctx; - } - - @Override - public ChannelPromise voidPromise() { - return channel.voidPromise(); - } - - void setRemoved() { - removed = true; - } - - @Override - public boolean isRemoved() { - return removed; - } - - private static void safeExecute(EventExecutor executor, Runnable runnable, ChannelPromise promise, Object msg) { - try { - executor.execute(runnable); - } catch (Throwable cause) { - try { - promise.setFailure(cause); - } finally { - if (msg != null) { - ReferenceCountUtil.release(msg); - } - } - } - } - - abstract static class AbstractWriteTask extends RecyclableMpscLinkedQueueNode implements Runnable { - private AbstractChannelHandlerContext ctx; - private Object msg; - private ChannelPromise promise; - private int size; - - private AbstractWriteTask(Recycler.Handle handle) { - super(handle); - } - - protected static void init(AbstractWriteTask task, AbstractChannelHandlerContext ctx, - Object msg, int size, ChannelPromise promise) { - task.ctx = ctx; - task.msg = msg; - task.promise = promise; - task.size = size; - } - - @Override - public final void run() { - try { - if (size > 0) { - ChannelOutboundBuffer buffer = ctx.channel.unsafe().outboundBuffer(); - // Check for null as it may be set to null if the channel is closed already - if (buffer != null) { - buffer.decrementPendingOutboundBytes(size); - } - } - write(ctx, msg, promise); - } finally { - // Set to null so the GC can collect them directly - ctx = null; - msg = null; - promise = null; - } - } - - @Override - public Runnable value() { - return this; - } - - protected void write(AbstractChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - ctx.invokeWrite(msg, promise); - } - } - - static final class WriteTask extends AbstractWriteTask implements SingleThreadEventLoop.NonWakeupRunnable { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected WriteTask newObject(Handle handle) { - return new WriteTask(handle); - } - }; - - private static WriteTask newInstance( - AbstractChannelHandlerContext ctx, Object msg, int size, ChannelPromise promise) { - WriteTask task = RECYCLER.get(); - init(task, ctx, msg, size, promise); - return task; - } - - private WriteTask(Recycler.Handle handle) { - super(handle); - } - - @Override - protected void recycle(Recycler.Handle handle) { - RECYCLER.recycle(this, handle); - } - } - - static final class WriteAndFlushTask extends AbstractWriteTask { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected WriteAndFlushTask newObject(Handle handle) { - return new WriteAndFlushTask(handle); - } - }; - - private static WriteAndFlushTask newInstance( - AbstractChannelHandlerContext ctx, Object msg, int size, ChannelPromise promise) { - WriteAndFlushTask task = RECYCLER.get(); - init(task, ctx, msg, size, promise); - return task; - } - - private WriteAndFlushTask(Recycler.Handle handle) { - super(handle); - } - - @Override - public void write(AbstractChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - super.write(ctx, msg, promise); - ctx.invokeFlush(); - } - - @Override - protected void recycle(Recycler.Handle handle) { - RECYCLER.recycle(this, handle); - } - } -} diff --git a/java/src/game/net/channel/AbstractServerChannel.java b/java/src/game/net/channel/AbstractServerChannel.java deleted file mode 100644 index a1d64cb..0000000 --- a/java/src/game/net/channel/AbstractServerChannel.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.SocketAddress; - -/** - * A skeletal server-side {@link Channel} implementation. A server-side - * {@link Channel} does not allow the following operations: - *
    - *
  • {@link #connect(SocketAddress, ChannelPromise)}
  • - *
  • {@link #disconnect(ChannelPromise)}
  • - *
  • {@link #write(Object, ChannelPromise)}
  • - *
  • {@link #flush()}
  • - *
  • and the shortcut methods which calls the methods mentioned above - *
- */ -public abstract class AbstractServerChannel extends AbstractChannel implements ServerChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - - /** - * Creates a new instance. - */ - protected AbstractServerChannel() { - super(null); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public SocketAddress remoteAddress() { - return null; - } - - @Override - protected SocketAddress remoteAddress0() { - return null; - } - - @Override - protected void doDisconnect() throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected AbstractUnsafe newUnsafe() { - return new DefaultServerUnsafe(); - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected final Object filterOutboundMessage(Object msg) { - throw new UnsupportedOperationException(); - } - - private final class DefaultServerUnsafe extends AbstractUnsafe { - @Override - public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - safeSetFailure(promise, new UnsupportedOperationException()); - } - } -} diff --git a/java/src/game/net/channel/AdaptiveRecvByteBufAllocator.java b/java/src/game/net/channel/AdaptiveRecvByteBufAllocator.java deleted file mode 100644 index 079ba92..0000000 --- a/java/src/game/net/channel/AdaptiveRecvByteBufAllocator.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.util.ArrayList; -import java.util.List; - -import game.net.buffer.ByteBuf; -import game.net.buffer.ByteBufAllocator; - -/** - * The {@link RecvByteBufAllocator} that automatically increases and - * decreases the predicted buffer size on feed back. - *

- * It gradually increases the expected number of readable bytes if the previous - * read fully filled the allocated buffer. It gradually decreases the expected - * number of readable bytes if the read operation was not able to fill a certain - * amount of the allocated buffer two times consecutively. Otherwise, it keeps - * returning the same prediction. - */ -public class AdaptiveRecvByteBufAllocator implements RecvByteBufAllocator { - - static final int DEFAULT_MINIMUM = 64; - static final int DEFAULT_INITIAL = 1024; - static final int DEFAULT_MAXIMUM = 65536; - - private static final int INDEX_INCREMENT = 4; - private static final int INDEX_DECREMENT = 1; - - private static final int[] SIZE_TABLE; - - static { - List sizeTable = new ArrayList(); - for (int i = 16; i < 512; i += 16) { - sizeTable.add(i); - } - - for (int i = 512; i > 0; i <<= 1) { - sizeTable.add(i); - } - - SIZE_TABLE = new int[sizeTable.size()]; - for (int i = 0; i < SIZE_TABLE.length; i ++) { - SIZE_TABLE[i] = sizeTable.get(i); - } - } - - public static final AdaptiveRecvByteBufAllocator DEFAULT = new AdaptiveRecvByteBufAllocator(); - - private static int getSizeTableIndex(final int size) { - for (int low = 0, high = SIZE_TABLE.length - 1;;) { - if (high < low) { - return low; - } - if (high == low) { - return high; - } - - int mid = low + high >>> 1; - int a = SIZE_TABLE[mid]; - int b = SIZE_TABLE[mid + 1]; - if (size > b) { - low = mid + 1; - } else if (size < a) { - high = mid - 1; - } else if (size == a) { - return mid; - } else { - return mid + 1; - } - } - } - - private static final class HandleImpl implements Handle { - private final int minIndex; - private final int maxIndex; - private int index; - private int nextReceiveBufferSize; - private boolean decreaseNow; - - HandleImpl(int minIndex, int maxIndex, int initial) { - this.minIndex = minIndex; - this.maxIndex = maxIndex; - - index = getSizeTableIndex(initial); - nextReceiveBufferSize = SIZE_TABLE[index]; - } - - @Override - public ByteBuf allocate(ByteBufAllocator alloc) { - return alloc.ioBuffer(nextReceiveBufferSize); - } - - @Override - public int guess() { - return nextReceiveBufferSize; - } - - @Override - public void record(int actualReadBytes) { - if (actualReadBytes <= SIZE_TABLE[Math.max(0, index - INDEX_DECREMENT - 1)]) { - if (decreaseNow) { - index = Math.max(index - INDEX_DECREMENT, minIndex); - nextReceiveBufferSize = SIZE_TABLE[index]; - decreaseNow = false; - } else { - decreaseNow = true; - } - } else if (actualReadBytes >= nextReceiveBufferSize) { - index = Math.min(index + INDEX_INCREMENT, maxIndex); - nextReceiveBufferSize = SIZE_TABLE[index]; - decreaseNow = false; - } - } - } - - private final int minIndex; - private final int maxIndex; - private final int initial; - - /** - * Creates a new predictor with the default parameters. With the default - * parameters, the expected buffer size starts from {@code 1024}, does not - * go down below {@code 64}, and does not go up above {@code 65536}. - */ - private AdaptiveRecvByteBufAllocator() { - this(DEFAULT_MINIMUM, DEFAULT_INITIAL, DEFAULT_MAXIMUM); - } - - /** - * Creates a new predictor with the specified parameters. - * - * @param minimum the inclusive lower bound of the expected buffer size - * @param initial the initial buffer size when no feed back was received - * @param maximum the inclusive upper bound of the expected buffer size - */ - public AdaptiveRecvByteBufAllocator(int minimum, int initial, int maximum) { - if (minimum <= 0) { - throw new IllegalArgumentException("minimum: " + minimum); - } - if (initial < minimum) { - throw new IllegalArgumentException("initial: " + initial); - } - if (maximum < initial) { - throw new IllegalArgumentException("maximum: " + maximum); - } - - int minIndex = getSizeTableIndex(minimum); - if (SIZE_TABLE[minIndex] < minimum) { - this.minIndex = minIndex + 1; - } else { - this.minIndex = minIndex; - } - - int maxIndex = getSizeTableIndex(maximum); - if (SIZE_TABLE[maxIndex] > maximum) { - this.maxIndex = maxIndex - 1; - } else { - this.maxIndex = maxIndex; - } - - this.initial = initial; - } - - @Override - public Handle newHandle() { - return new HandleImpl(minIndex, maxIndex, initial); - } -} diff --git a/java/src/game/net/channel/Channel.java b/java/src/game/net/channel/Channel.java deleted file mode 100644 index d29a135..0000000 --- a/java/src/game/net/channel/Channel.java +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.SocketAddress; - -import game.net.buffer.ByteBufAllocator; -import game.net.util.AttributeMap; - - -/** - * A nexus to a network socket or a component which is capable of I/O - * operations such as read, write, connect, and bind. - *

- * A channel provides a user: - *

    - *
  • the current state of the channel (e.g. is it open? is it connected?),
  • - *
  • the {@linkplain ChannelConfig configuration parameters} of the channel (e.g. receive buffer size),
  • - *
  • the I/O operations that the channel supports (e.g. read, write, connect, and bind), and
  • - *
  • the {@link ChannelPipeline} which handles all I/O events and requests - * associated with the channel.
  • - *
- * - *

All I/O operations are asynchronous.

- *

- * All I/O operations in Netty are asynchronous. It means any I/O calls will - * return immediately with no guarantee that the requested I/O operation has - * been completed at the end of the call. Instead, you will be returned with - * a {@link ChannelFuture} instance which will notify you when the requested I/O - * operation has succeeded, failed, or canceled. - * - *

Channels are hierarchical

- *

- * A {@link Channel} can have a {@linkplain #parent() parent} depending on - * how it was created. For instance, a {@link SocketChannel}, that was accepted - * by {@link ServerSocketChannel}, will return the {@link ServerSocketChannel} - * as its parent on {@link #parent()}. - *

- * The semantics of the hierarchical structure depends on the transport - * implementation where the {@link Channel} belongs to. For example, you could - * write a new {@link Channel} implementation that creates the sub-channels that - * share one socket connection, as BEEP and - * SSH do. - * - *

Downcast to access transport-specific operations

- *

- * Some transports exposes additional operations that is specific to the - * transport. Down-cast the {@link Channel} to sub-type to invoke such - * operations. For example, with the old I/O datagram transport, multicast - * join / leave operations are provided by {@link DatagramChannel}. - * - *

Release resources

- *

- * It is important to call {@link #close()} or {@link #close(ChannelPromise)} to release all - * resources once you are done with the {@link Channel}. This ensures all resources are - * released in a proper way, i.e. filehandles. - */ -public interface Channel extends AttributeMap, Comparable { - - /** - * Return the {@link EventLoop} this {@link Channel} was registered too. - */ - EventLoop eventLoop(); - - /** - * Returns the parent of this channel. - * - * @return the parent channel. - * {@code null} if this channel does not have a parent channel. - */ - Channel parent(); - - /** - * Returns the configuration of this channel. - */ - ChannelConfig config(); - - /** - * Returns {@code true} if the {@link Channel} is open an may get active later - */ - boolean isOpen(); - - /** - * Returns {@code true} if the {@link Channel} is registered with an {@link EventLoop}. - */ - boolean isRegistered(); - - /** - * Return {@code true} if the {@link Channel} is active and so connected. - */ - boolean isActive(); - - /** - * Return the {@link ChannelMetadata} of the {@link Channel} which describe the nature of the {@link Channel}. - */ - ChannelMetadata metadata(); - - /** - * Returns the local address where this channel is bound to. The returned - * {@link SocketAddress} is supposed to be down-cast into more concrete - * type such as {@link InetSocketAddress} to retrieve the detailed - * information. - * - * @return the local address of this channel. - * {@code null} if this channel is not bound. - */ - SocketAddress localAddress(); - - /** - * Returns the remote address where this channel is connected to. The - * returned {@link SocketAddress} is supposed to be down-cast into more - * concrete type such as {@link InetSocketAddress} to retrieve the detailed - * information. - * - * @return the remote address of this channel. - * {@code null} if this channel is not connected. - * If this channel is not connected but it can receive messages - * from arbitrary remote addresses (e.g. {@link DatagramChannel}, - * use {@link DatagramPacket#recipient()} to determine - * the origination of the received message as this method will - * return {@code null}. - */ - SocketAddress remoteAddress(); - - /** - * Returns the {@link ChannelFuture} which will be notified when this - * channel is closed. This method always returns the same future instance. - */ - ChannelFuture closeFuture(); - - /** - * Returns {@code true} if and only if the I/O thread will perform the - * requested write operation immediately. Any write requests made when - * this method returns {@code false} are queued until the I/O thread is - * ready to process the queued write requests. - */ - boolean isWritable(); - - /** - * Returns an internal-use-only object that provides unsafe operations. - */ - Unsafe unsafe(); - - /** - * Return the assigned {@link ChannelPipeline} - */ - ChannelPipeline pipeline(); - - /** - * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. - */ - ByteBufAllocator alloc(); - - /** - * Return a new {@link ChannelPromise}. - */ - ChannelPromise newPromise(); - - /** - * Return an new {@link ChannelProgressivePromise} - */ -// ChannelProgressivePromise newProgressivePromise(); - - /** - * Create a new {@link ChannelFuture} which is marked as succeeded already. So {@link ChannelFuture#isSuccess()} - * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newSucceededFuture(); - - /** - * Create a new {@link ChannelFuture} which is marked as failed already. So {@link ChannelFuture#isSuccess()} - * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newFailedFuture(Throwable cause); - - /** - * Return a special ChannelPromise which can be reused for different operations. - *

- * It's only supported to use - * it for {@link Channel#write(Object, ChannelPromise)}. - *

- *

- * Be aware that the returned {@link ChannelPromise} will not support most operations and should only be used - * if you want to save an object allocation for every write operation. You will not be able to detect if the - * operation was complete, only if it failed as the implementation will call - * {@link ChannelPipeline#fireExceptionCaught(Throwable)} in this case. - *

- * Be aware this is an expert feature and should be used with care! - */ - ChannelPromise voidPromise(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(); - - /** - * Request to close this {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(); - - /** - * Request to deregister this {@link Channel} from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - * - */ - ChannelFuture deregister(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelFuture} will be notified. - * - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified and also returned. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(ChannelPromise promise); - - /** - * Request to close this {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(ChannelPromise promise); - - /** - * Request to deregister this {@link Channel} from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture deregister(ChannelPromise promise); - - /** - * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an - * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was - * read, and triggers a - * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the - * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. - *

- * This will result in having the - * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - Channel read(); - - /** - * Request to write a message via this {@link Channel} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg); - - /** - * Request to write a message via this {@link Channel} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg, ChannelPromise promise); - - /** - * Request to flush all pending messages. - */ - Channel flush(); - - /** - * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); - - /** - * Shortcut for call {@link #write(Object)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg); - - /** - * Unsafe operations that should never be called from user-code. These methods - * are only provided to implement the actual transport, and must be invoked from an I/O thread except for the - * following methods: - *

    - *
  • {@link #localAddress()}
  • - *
  • {@link #remoteAddress()}
  • - *
  • {@link #closeForcibly()}
  • - *
  • {@link #register(EventLoop, ChannelPromise)}
  • - *
  • {@link #voidPromise()}
  • - *
- */ - interface Unsafe { - /** - * Return the {@link SocketAddress} to which is bound local or - * {@code null} if none. - */ - SocketAddress localAddress(); - - /** - * Return the {@link SocketAddress} to which is bound remote or - * {@code null} if none is bound yet. - */ - SocketAddress remoteAddress(); - - /** - * Register the {@link Channel} of the {@link ChannelPromise} with the {@link EventLoop} and notify - * the {@link ChannelFuture} once the registration was complete. - */ - void register(EventLoop eventLoop, ChannelPromise promise); - - /** - * Bind the {@link SocketAddress} to the {@link Channel} of the {@link ChannelPromise} and notify - * it once its done. - */ - void bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Connect the {@link Channel} of the given {@link ChannelFuture} with the given remote {@link SocketAddress}. - * If a specific local {@link SocketAddress} should be used it need to be given as argument. Otherwise just - * pass {@code null} to it. - * - * The {@link ChannelPromise} will get notified once the connect operation was complete. - */ - void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Disconnect the {@link Channel} of the {@link ChannelFuture} and notify the {@link ChannelPromise} once the - * operation was complete. - */ - void disconnect(ChannelPromise promise); - - /** - * Close the {@link Channel} of the {@link ChannelPromise} and notify the {@link ChannelPromise} once the - * operation was complete. - */ - void close(ChannelPromise promise); - - /** - * Closes the {@link Channel} immediately without firing any events. Probably only useful - * when registration attempt failed. - */ - void closeForcibly(); - - /** - * Deregister the {@link Channel} of the {@link ChannelPromise} from {@link EventLoop} and notify the - * {@link ChannelPromise} once the operation was complete. - */ - void deregister(ChannelPromise promise); - - /** - * Schedules a read operation that fills the inbound buffer of the first {@link ChannelInboundHandler} in the - * {@link ChannelPipeline}. If there's already a pending read operation, this method does nothing. - */ - void beginRead(); - - /** - * Schedules a write operation. - */ - void write(Object msg, ChannelPromise promise); - - /** - * Flush out all write operations scheduled via {@link #write(Object, ChannelPromise)}. - */ - void flush(); - - /** - * Return a special ChannelPromise which can be reused and passed to the operations in {@link Unsafe}. - * It will never be notified of a success or error and so is only a placeholder for operations - * that take a {@link ChannelPromise} as argument but for which you not want to get notified. - */ - ChannelPromise voidPromise(); - - /** - * Returns the {@link ChannelOutboundBuffer} of the {@link Channel} where the pending write requests are stored. - */ - ChannelOutboundBuffer outboundBuffer(); - } -} diff --git a/java/src/game/net/channel/ChannelConfig.java b/java/src/game/net/channel/ChannelConfig.java deleted file mode 100644 index f4c6bba..0000000 --- a/java/src/game/net/channel/ChannelConfig.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.util.Map; - -import game.net.buffer.ByteBufAllocator; - -/** - * A set of configuration properties of a {@link Channel}. - *

- * Please down-cast to more specific configuration type such as - * {@link SocketChannelConfig} or use {@link #setOptions(Map)} to set the - * transport-specific properties: - *

- * {@link Channel} ch = ...;
- * {@link SocketChannelConfig} cfg = ({@link SocketChannelConfig}) ch.getConfig();
- * cfg.setTcpNoDelay(false);
- * 
- * - *

Option map

- * - * An option map property is a dynamic write-only property which allows - * the configuration of a {@link Channel} without down-casting its associated - * {@link ChannelConfig}. To update an option map, please call {@link #setOptions(Map)}. - *

- * All {@link ChannelConfig} has the following options: - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameAssociated setter method
{@link ChannelOption#CONNECT_TIMEOUT_MILLIS}{@link #setConnectTimeoutMillis(int)}
{@link ChannelOption#WRITE_SPIN_COUNT}{@link #setWriteSpinCount(int)}
{@link ChannelOption#ALLOCATOR}{@link #setAllocator(ByteBufAllocator)}
{@link ChannelOption#AUTO_READ}{@link #setAutoRead(boolean)}
- *

- * More options are available in the sub-types of {@link ChannelConfig}. For - * example, you can configure the parameters which are specific to a TCP/IP - * socket as explained in {@link SocketChannelConfig}. - */ -public interface ChannelConfig { - - /** - * Return all set {@link ChannelOption}'s. - */ - Map, Object> getOptions(); - - /** - * Sets the configuration properties from the specified {@link Map}. - */ - boolean setOptions(Map, ?> options); - - /** - * Return the value of the given {@link ChannelOption} - */ - T getOption(ChannelOption option); - - /** - * Sets a configuration property with the specified name and value. - * To override this method properly, you must call the super class: - *

-     * public boolean setOption(ChannelOption<T> option, T value) {
-     *     if (super.setOption(option, value)) {
-     *         return true;
-     *     }
-     *
-     *     if (option.equals(additionalOption)) {
-     *         ....
-     *         return true;
-     *     }
-     *
-     *     return false;
-     * }
-     * 
- * - * @return {@code true} if and only if the property has been set - */ - boolean setOption(ChannelOption option, T value); - - /** - * Returns the connect timeout of the channel in milliseconds. If the - * {@link Channel} does not support connect operation, this property is not - * used at all, and therefore will be ignored. - * - * @return the connect timeout in milliseconds. {@code 0} if disabled. - */ - int getConnectTimeoutMillis(); - - /** - * Sets the connect timeout of the channel in milliseconds. If the - * {@link Channel} does not support connect operation, this property is not - * used at all, and therefore will be ignored. - * - * @param connectTimeoutMillis the connect timeout in milliseconds. - * {@code 0} to disable. - */ - ChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - /** - * Returns the maximum number of messages to read per read loop. - * a {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object) channelRead()} event. - * If this value is greater than 1, an event loop might attempt to read multiple times to procure multiple messages. - */ - int getMaxMessagesPerRead(); - - /** - * Sets the maximum number of messages to read per read loop. - * If this value is greater than 1, an event loop might attempt to read multiple times to procure multiple messages. - */ - ChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - /** - * Returns the maximum loop count for a write operation until - * {@link WritableByteChannel#write(ByteBuffer)} returns a non-zero value. - * It is similar to what a spin lock is used for in concurrency programming. - * It improves memory utilization and write throughput depending on - * the platform that JVM runs on. The default value is {@code 16}. - */ - int getWriteSpinCount(); - - /** - * Sets the maximum loop count for a write operation until - * {@link WritableByteChannel#write(ByteBuffer)} returns a non-zero value. - * It is similar to what a spin lock is used for in concurrency programming. - * It improves memory utilization and write throughput depending on - * the platform that JVM runs on. The default value is {@code 16}. - * - * @throws IllegalArgumentException - * if the specified value is {@code 0} or less than {@code 0} - */ - ChannelConfig setWriteSpinCount(int writeSpinCount); - - /** - * Returns {@link ByteBufAllocator} which is used for the channel - * to allocate buffers. - */ - ByteBufAllocator getAllocator(); - - /** - * Set the {@link ByteBufAllocator} which is used for the channel - * to allocate buffers. - */ - ChannelConfig setAllocator(ByteBufAllocator allocator); - - /** - * Returns {@link RecvByteBufAllocator} which is used for the channel - * to allocate receive buffers. - */ - RecvByteBufAllocator getRecvByteBufAllocator(); - - /** - * Set the {@link ByteBufAllocator} which is used for the channel - * to allocate receive buffers. - */ - ChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - /** - * Returns {@code true} if and only if {@link ChannelHandlerContext#read()} will be invoked automatically so that - * a user application doesn't need to call it at all. The default value is {@code true}. - */ - boolean isAutoRead(); - - /** - * Sets if {@link ChannelHandlerContext#read()} will be invoked automatically so that a user application doesn't - * need to call it at all. The default value is {@code true}. - */ - ChannelConfig setAutoRead(boolean autoRead); - - /** - * @deprecated From version 5.0, {@link Channel} will not be closed on write failure. - * - * Returns {@code true} if and only if the {@link Channel} will be closed automatically and immediately on - * write failure. The default is {@code false}. - */ - @Deprecated - boolean isAutoClose(); - - /** - * @deprecated From version 5.0, {@link Channel} will not be closed on write failure. - * - * Sets whether the {@link Channel} should be closed automatically and immediately on write faillure. - * The default is {@code false}. - */ - @Deprecated - ChannelConfig setAutoClose(boolean autoClose); - - /** - * Returns the high water mark of the write buffer. If the number of bytes - * queued in the write buffer exceeds this value, {@link Channel#isWritable()} - * will start to return {@code false}. - */ - int getWriteBufferHighWaterMark(); - - /** - * Sets the high water mark of the write buffer. If the number of bytes - * queued in the write buffer exceeds this value, {@link Channel#isWritable()} - * will start to return {@code false}. - */ - ChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); - - /** - * Returns the low water mark of the write buffer. Once the number of bytes - * queued in the write buffer exceeded the - * {@linkplain #setWriteBufferHighWaterMark(int) high water mark} and then - * dropped down below this value, {@link Channel#isWritable()} will start to return - * {@code true} again. - */ - int getWriteBufferLowWaterMark(); - - /** - * Sets the low water mark of the write buffer. Once the number of bytes - * queued in the write buffer exceeded the - * {@linkplain #setWriteBufferHighWaterMark(int) high water mark} and then - * dropped down below this value, {@link Channel#isWritable()} will start to return - * {@code true} again. - */ - ChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark); - - /** - * Returns {@link MessageSizeEstimator} which is used for the channel - * to detect the size of a message. - */ - MessageSizeEstimator getMessageSizeEstimator(); - - /** - * Set the {@link ByteBufAllocator} which is used for the channel - * to detect the size of a message. - */ - ChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/java/src/game/net/channel/ChannelException.java b/java/src/game/net/channel/ChannelException.java deleted file mode 100644 index 828efde..0000000 --- a/java/src/game/net/channel/ChannelException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * A {@link RuntimeException} which is thrown when an I/O operation fails. - */ -public class ChannelException extends RuntimeException { - - private static final long serialVersionUID = 2908618315971075004L; - - /** - * Creates a new exception. - */ - public ChannelException() { - } - - /** - * Creates a new exception. - */ - public ChannelException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new exception. - */ - public ChannelException(String message) { - super(message); - } - - /** - * Creates a new exception. - */ - public ChannelException(Throwable cause) { - super(cause); - } -} diff --git a/java/src/game/net/channel/ChannelFuture.java b/java/src/game/net/channel/ChannelFuture.java deleted file mode 100644 index 0853756..0000000 --- a/java/src/game/net/channel/ChannelFuture.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; - - -/** - * The result of an asynchronous {@link Channel} I/O operation. - *

- * All I/O operations in Netty are asynchronous. It means any I/O calls will - * return immediately with no guarantee that the requested I/O operation has - * been completed at the end of the call. Instead, you will be returned with - * a {@link ChannelFuture} instance which gives you the information about the - * result or status of the I/O operation. - *

- * A {@link ChannelFuture} is either uncompleted or completed. - * When an I/O operation begins, a new future object is created. The new future - * is uncompleted initially - it is neither succeeded, failed, nor cancelled - * because the I/O operation is not finished yet. If the I/O operation is - * finished either successfully, with failure, or by cancellation, the future is - * marked as completed with more specific information, such as the cause of the - * failure. Please note that even failure and cancellation belong to the - * completed state. - *

- *                                      +---------------------------+
- *                                      | Completed successfully    |
- *                                      +---------------------------+
- *                                 +---->      isDone() = true      |
- * +--------------------------+    |    |   isSuccess() = true      |
- * |        Uncompleted       |    |    +===========================+
- * +--------------------------+    |    | Completed with failure    |
- * |      isDone() = false    |    |    +---------------------------+
- * |   isSuccess() = false    |----+---->   isDone() = true         |
- * | isCancelled() = false    |    |    | cause() = non-null     |
- * |    cause() = null     |    |    +===========================+
- * +--------------------------+    |    | Completed by cancellation |
- *                                 |    +---------------------------+
- *                                 +---->      isDone() = true      |
- *                                      | isCancelled() = true      |
- *                                      +---------------------------+
- * 
- * - * Various methods are provided to let you check if the I/O operation has been - * completed, wait for the completion, and retrieve the result of the I/O - * operation. It also allows you to add {@link ChannelFutureListener}s so you - * can get notified when the I/O operation is completed. - * - *

Prefer {@link #addListener(GenericFutureListener)} to {@link #await()}

- * - * It is recommended to prefer {@link #addListener(GenericFutureListener)} to - * {@link #await()} wherever possible to get notified when an I/O operation is - * done and to do any follow-up tasks. - *

- * {@link #addListener(GenericFutureListener)} is non-blocking. It simply adds - * the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and - * I/O thread will notify the listeners when the I/O operation associated with - * the future is done. {@link ChannelFutureListener} yields the best - * performance and resource utilization because it does not block at all, but - * it could be tricky to implement a sequential logic if you are not used to - * event-driven programming. - *

- * By contrast, {@link #await()} is a blocking operation. Once called, the - * caller thread blocks until the operation is done. It is easier to implement - * a sequential logic with {@link #await()}, but the caller thread blocks - * unnecessarily until the I/O operation is done and there's relatively - * expensive cost of inter-thread notification. Moreover, there's a chance of - * dead lock in a particular circumstance, which is described below. - * - *

Do not call {@link #await()} inside {@link ChannelHandler}

- *

- * The event handler methods in {@link ChannelHandler} is usually called by - * an I/O thread. If {@link #await()} is called by an event handler - * method, which is called by the I/O thread, the I/O operation it is waiting - * for might never be complete because {@link #await()} can block the I/O - * operation it is waiting for, which is a dead lock. - *

- * // BAD - NEVER DO THIS
- * {@code @Override}
- * public void channelRead({@link ChannelHandlerContext} ctx, GoodByeMessage msg) {
- *     {@link ChannelFuture} future = ctx.channel().close();
- *     future.awaitUninterruptibly();
- *     // Perform post-closure operation
- *     // ...
- * }
- *
- * // GOOD
- * {@code @Override}
- * public void channelRead({@link ChannelHandlerContext} ctx,  GoodByeMessage msg) {
- *     {@link ChannelFuture} future = ctx.channel().close();
- *     future.addListener(new {@link ChannelFutureListener}() {
- *         public void operationComplete({@link ChannelFuture} future) {
- *             // Perform post-closure operation
- *             // ...
- *         }
- *     });
- * }
- * 
- *

- * In spite of the disadvantages mentioned above, there are certainly the cases - * where it is more convenient to call {@link #await()}. In such a case, please - * make sure you do not call {@link #await()} in an I/O thread. Otherwise, - * {@link BlockingOperationException} will be raised to prevent a dead lock. - * - *

Do not confuse I/O timeout and await timeout

- * - * The timeout value you specify with {@link #await(long)}, - * {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or - * {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O - * timeout at all. If an I/O operation times out, the future will be marked as - * 'completed with failure,' as depicted in the diagram above. For example, - * connect timeout should be configured via a transport-specific option: - *
- * // BAD - NEVER DO THIS
- * {@link Bootstrap} b = ...;
- * {@link ChannelFuture} f = b.connect(...);
- * f.awaitUninterruptibly(10, TimeUnit.SECONDS);
- * if (f.isCancelled()) {
- *     // Connection attempt cancelled by user
- * } else if (!f.isSuccess()) {
- *     // You might get a NullPointerException here because the future
- *     // might not be completed yet.
- *     f.cause().printStackTrace();
- * } else {
- *     // Connection established successfully
- * }
- *
- * // GOOD
- * {@link Bootstrap} b = ...;
- * // Configure the connect timeout option.
- * b.option({@link ChannelOption}.CONNECT_TIMEOUT_MILLIS, 10000);
- * {@link ChannelFuture} f = b.connect(...);
- * f.awaitUninterruptibly();
- *
- * // Now we are sure the future is completed.
- * assert f.isDone();
- *
- * if (f.isCancelled()) {
- *     // Connection attempt cancelled by user
- * } else if (!f.isSuccess()) {
- *     f.cause().printStackTrace();
- * } else {
- *     // Connection established successfully
- * }
- * 
- */ -public interface ChannelFuture extends Future { - - /** - * Returns a channel where the I/O operation associated with this - * future takes place. - */ - Channel channel(); - - @Override - ChannelFuture addListener(GenericFutureListener> listener); - - @Override - ChannelFuture addListeners(GenericFutureListener>... listeners); - - @Override - ChannelFuture removeListener(GenericFutureListener> listener); - - @Override - ChannelFuture removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelFuture sync() throws InterruptedException; - - @Override - ChannelFuture syncUninterruptibly(); - - @Override - ChannelFuture await() throws InterruptedException; - - @Override - ChannelFuture awaitUninterruptibly(); -} diff --git a/java/src/game/net/channel/ChannelFutureListener.java b/java/src/game/net/channel/ChannelFutureListener.java deleted file mode 100644 index 79aff6b..0000000 --- a/java/src/game/net/channel/ChannelFutureListener.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.GenericFutureListener; - - -/** - * Listens to the result of a {@link ChannelFuture}. The result of the - * asynchronous {@link Channel} I/O operation is notified once this listener - * is added by calling {@link ChannelFuture#addListener(GenericFutureListener)}. - * - *

Return the control to the caller quickly

- * - * {@link #operationComplete(Future)} is directly called by an I/O - * thread. Therefore, performing a time consuming task or a blocking operation - * in the handler method can cause an unexpected pause during I/O. If you need - * to perform a blocking operation on I/O completion, try to execute the - * operation in a different thread using a thread pool. - */ -public interface ChannelFutureListener extends GenericFutureListener { - - /** - * A {@link ChannelFutureListener} that closes the {@link Channel} which is - * associated with the specified {@link ChannelFuture}. - */ - ChannelFutureListener CLOSE = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - future.channel().close(); - } - }; - - /** - * A {@link ChannelFutureListener} that closes the {@link Channel} when the - * operation ended up with a failure or cancellation rather than a success. - */ - ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - if (!future.isSuccess()) { - future.channel().close(); - } - } - }; - - /** - * A {@link ChannelFutureListener} that forwards the {@link Throwable} of the {@link ChannelFuture} into the - * {@link ChannelPipeline}. This mimics the old behavior of Netty 3. - */ - ChannelFutureListener FIRE_EXCEPTION_ON_FAILURE = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - if (!future.isSuccess()) { - future.channel().pipeline().fireExceptionCaught(future.cause()); - } - } - }; - - // Just a type alias -} diff --git a/java/src/game/net/channel/ChannelHandler.java b/java/src/game/net/channel/ChannelHandler.java deleted file mode 100644 index 2f84869..0000000 --- a/java/src/game/net/channel/ChannelHandler.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Handles or intercepts a {@link ChannelInboundInvoker} or {@link ChannelOutboundInvoker} operation, and forwards it - * to the next handler in a {@link ChannelPipeline}. - * - *

Sub-types

- *

- * {@link ChannelHandler} itself does not provide many methods. To handle a - * a {@link ChannelInboundInvoker} or {@link ChannelOutboundInvoker} operation - * you need to implement its sub-interfaces. There are many different sub-interfaces - * which handles inbound and outbound operations. - * - * But the most useful for developers may be: - *

    - *
  • {@link ChannelInboundHandlerAdapter} handles and intercepts inbound operations
  • - *
  • {@link ChannelOutboundHandlerAdapter} handles and intercepts outbound operations
  • - *
- * - * You will also find more detailed explanation from the documentation of - * each sub-interface on how an event is interpreted when it goes upstream and - * downstream respectively. - * - *

The context object

- *

- * A {@link ChannelHandler} is provided with a {@link ChannelHandlerContext} - * object. A {@link ChannelHandler} is supposed to interact with the - * {@link ChannelPipeline} it belongs to via a context object. Using the - * context object, the {@link ChannelHandler} can pass events upstream or - * downstream, modify the pipeline dynamically, or store the information - * (using {@link AttributeKey}s) which is specific to the handler. - * - *

State management

- * - * A {@link ChannelHandler} often needs to store some stateful information. - * The simplest and recommended approach is to use member variables: - *
- * public interface Message {
- *     // your methods here
- * }
- *
- * public class DataServerHandler extends {@link SimpleChannelInboundHandler}<Message> {
- *
- *     private boolean loggedIn;
- *
- *     {@code @Override}
- *     public void channelRead0({@link ChannelHandlerContext} ctx, Message message) {
- *         {@link Channel} ch = e.getChannel();
- *         if (message instanceof LoginMessage) {
- *             authenticate((LoginMessage) message);
- *             loggedIn = true;
- *         } else (message instanceof GetDataMessage) {
- *             if (loggedIn) {
- *                 ch.write(fetchSecret((GetDataMessage) message));
- *             } else {
- *                 fail();
- *             }
- *         }
- *     }
- *     ...
- * }
- * 
- * Because the handler instance has a state variable which is dedicated to - * one connection, you have to create a new handler instance for each new - * channel to avoid a race condition where a unauthenticated client can get - * the confidential information: - *
- * // Create a new handler instance per channel.
- * // See {@link ChannelInitializer#initChannel(Channel)}.
- * public class DataServerInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *     {@code @Override}
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("handler", new DataServerHandler());
- *     }
- * }
- *
- * 
- * - *

Using {@link AttributeKey}

- * - * Although it's recommended to use member variables to store the state of a - * handler, for some reason you might not want to create many handler instances. - * In such a case, you can use {@link AttributeKey}s which is provided by - * {@link ChannelHandlerContext}: - *
- * public interface Message {
- *     // your methods here
- * }
- *
- * {@code @Sharable}
- * public class DataServerHandler extends {@link SimpleChannelInboundHandler}<Message> {
- *     private final {@link AttributeKey}<{@link Boolean}> auth =
- *           {@link AttributeKey#valueOf(String) AttributeKey.valueOf("auth")};
- *
- *     {@code @Override}
- *     public void channelRead({@link ChannelHandlerContext} ctx, Message message) {
- *         {@link Attribute}<{@link Boolean}> attr = ctx.attr(auth);
- *         {@link Channel} ch = ctx.channel();
- *         if (message instanceof LoginMessage) {
- *             authenticate((LoginMessage) o);
- *             attr.set(true);
- *         } else (message instanceof GetDataMessage) {
- *             if (Boolean.TRUE.equals(attr.get())) {
- *                 ch.write(fetchSecret((GetDataMessage) o));
- *             } else {
- *                 fail();
- *             }
- *         }
- *     }
- *     ...
- * }
- * 
- * Now that the state of the handler isattached to the {@link ChannelHandlerContext}, you can add the - * same handler instance to different pipelines: - *
- * public class DataServerInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *
- *     private static final DataServerHandler SHARED = new DataServerHandler();
- *
- *     {@code @Override}
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("handler", SHARED);
- *     }
- * }
- * 
- * - * - *

The {@code @Sharable} annotation

- *

- * In the example above which used an {@link AttributeKey}, - * you might have noticed the {@code @Sharable} annotation. - *

- * If a {@link ChannelHandler} is annotated with the {@code @Sharable} - * annotation, it means you can create an instance of the handler just once and - * add it to one or more {@link ChannelPipeline}s multiple times without - * a race condition. - *

- * If this annotation is not specified, you have to create a new handler - * instance every time you add it to a pipeline because it has unshared state - * such as member variables. - *

- * This annotation is provided for documentation purpose, just like - * the JCIP annotations. - * - *

Additional resources worth reading

- *

- * Please refer to the {@link ChannelHandler}, and - * {@link ChannelPipeline} to find out more about inbound and outbound operations, - * what fundamental differences they have, how they flow in a pipeline, and how to handle - * the operation in your application. - */ -public interface ChannelHandler { - - /** - * Gets called after the {@link ChannelHandler} was added to the actual context and it's ready to handle events. - */ - void handlerAdded(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called after the {@link ChannelHandler} was removed from the actual context and it doesn't handle events - * anymore. - */ - void handlerRemoved(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called if a {@link Throwable} was thrown. - */ - void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception; - - /** - * Indicates that the same instance of the annotated {@link ChannelHandler} - * can be added to one or more {@link ChannelPipeline}s multiple times - * without a race condition. - *

- * If this annotation is not specified, you have to create a new handler - * instance every time you add it to a pipeline because it has unshared - * state such as member variables. - *

- * This annotation is provided for documentation purpose, just like - * the JCIP annotations. - */ - @Inherited - @Documented - @Target(ElementType.TYPE) - @Retention(RetentionPolicy.RUNTIME) - @interface Sharable { - // no value - } -} diff --git a/java/src/game/net/channel/ChannelHandlerAdapter.java b/java/src/game/net/channel/ChannelHandlerAdapter.java deleted file mode 100644 index 8af3544..0000000 --- a/java/src/game/net/channel/ChannelHandlerAdapter.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.channel; - -import java.util.Map; - -import game.net.util.internal.InternalThreadLocalMap; - -/** - * Skelton implementation of a {@link ChannelHandler}. - */ -public abstract class ChannelHandlerAdapter implements ChannelHandler { - - // Not using volatile because it's used only for a sanity check. - boolean added; - - /** - * Return {@code true} if the implementation is {@link Sharable} and so can be added - * to different {@link ChannelPipeline}s. - */ - public boolean isSharable() { - /** - * Cache the result of {@link Sharable} annotation detection to workaround a condition. We use a - * {@link ThreadLocal} and {@link WeakHashMap} to eliminate the volatile write/reads. Using different - * {@link WeakHashMap} instances per {@link Thread} is good enough for us and the number of - * {@link Thread}s are quite limited anyway. - * - * See #2289. - */ - Class clazz = getClass(); - Map, Boolean> cache = InternalThreadLocalMap.get().handlerSharableCache(); - Boolean sharable = cache.get(clazz); - if (sharable == null) { - sharable = clazz.isAnnotationPresent(Sharable.class); - cache.put(clazz, sharable); - } - return sharable; - } - - /** - * Do nothing by default, sub-classes may override this method. - */ - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - /** - * Do nothing by default, sub-classes may override this method. - */ - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - /** - * Calls {@link ChannelHandlerContext#fireExceptionCaught(Throwable)} to forward - * to the next {@link ChannelHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ctx.fireExceptionCaught(cause); - } -} diff --git a/java/src/game/net/channel/ChannelHandlerContext.java b/java/src/game/net/channel/ChannelHandlerContext.java deleted file mode 100644 index 242358d..0000000 --- a/java/src/game/net/channel/ChannelHandlerContext.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - - -import java.net.SocketAddress; - -import game.net.buffer.ByteBufAllocator; -import game.net.util.AttributeMap; -import game.net.util.concurrent.EventExecutor; - -/** - * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline} - * and other handlers. A handler can notify the next {@link ChannelHandler} in the {@link ChannelPipeline}, - * modify the {@link ChannelPipeline} it belongs to dynamically. - * - *

Notify

- * - * You can notify the closest handler in the - * same {@link ChannelPipeline} by calling one of the various methods provided here. - * Please refer to {@link ChannelPipeline} to understand how an event flows. - * - *

Modifying a pipeline

- * - * You can get the {@link ChannelPipeline} your handler belongs to by calling - * {@link #pipeline()}. A non-trivial application could insert, remove, or - * replace handlers in the pipeline dynamically at runtime. - * - *

Retrieving for later use

- * - * You can keep the {@link ChannelHandlerContext} for later use, such as - * triggering an event outside the handler methods, even from a different thread. - *
- * public class MyHandler extends {@link ChannelDuplexHandler} {
- *
- *     private {@link ChannelHandlerContext} ctx;
- *
- *     public void beforeAdd({@link ChannelHandlerContext} ctx) {
- *         this.ctx = ctx;
- *     }
- *
- *     public void login(String username, password) {
- *         ctx.write(new LoginMessage(username, password));
- *     }
- *     ...
- * }
- * 
- * - *

Storing stateful information

- * - * {@link #attr(AttributeKey)} allow you to - * store and access stateful information that is related with a handler and its - * context. Please refer to {@link ChannelHandler} to learn various recommended - * ways to manage stateful information. - * - *

A handler can have more than one context

- * - * Please note that a {@link ChannelHandler} instance can be added to more than - * one {@link ChannelPipeline}. It means a single {@link ChannelHandler} - * instance can have more than one {@link ChannelHandlerContext} and therefore - * the single instance can be invoked with different - * {@link ChannelHandlerContext}s if it is added to one or more - * {@link ChannelPipeline}s more than once. - *

- * For example, the following handler will have as many independent {@link AttributeKey}s - * as how many times it is added to pipelines, regardless if it is added to the - * same pipeline multiple times or added to different pipelines multiple times: - *

- * public class FactorialHandler extends {@link ChannelInboundHandlerAdapter}<{@link Integer}> {
- *
- *   private final {@link AttributeKey}<{@link Integer}> counter =
- *           new {@link AttributeKey}<{@link Integer}>("counter");
- *
- *   // This handler will receive a sequence of increasing integers starting
- *   // from 1.
- *   {@code @Override}
- *   public void channelRead({@link ChannelHandlerContext} ctx, {@link Integer} integer) {
- *     {@link Attribute}<{@link Integer}> attr = ctx.getAttr(counter);
- *     Integer a = ctx.getAttr(counter).get();
- *
- *     if (a == null) {
- *       a = 1;
- *     }
- *
- *     attr.set(a * integer));
- *   }
- * }
- *
- * // Different context objects are given to "f1", "f2", "f3", and "f4" even if
- * // they refer to the same handler instance.  Because the FactorialHandler
- * // stores its state in a context object (as an (using an {@link AttributeKey}), the factorial is
- * // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
- * FactorialHandler fh = new FactorialHandler();
- *
- * {@link ChannelPipeline} p1 = {@link Channels}.pipeline();
- * p1.addLast("f1", fh);
- * p1.addLast("f2", fh);
- *
- * {@link ChannelPipeline} p2 = {@link Channels}.pipeline();
- * p2.addLast("f3", fh);
- * p2.addLast("f4", fh);
- * 
- * - *

Additional resources worth reading

- *

- * Please refer to the {@link ChannelHandler}, and - * {@link ChannelPipeline} to find out more about inbound and outbound operations, - * what fundamental differences they have, how they flow in a pipeline, and how to handle - * the operation in your application. - */ -public interface ChannelHandlerContext - extends AttributeMap { - - /** - * Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}. - */ - Channel channel(); - - /** - * The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly - * submit tasks that get executed in the event loop. For more information please refer to the - * {@link EventExecutor} javadoc. - */ - EventExecutor executor(); - - /** - * The unique name of the {@link ChannelHandlerContext}.The name was used when then {@link ChannelHandler} - * was added to the {@link ChannelPipeline}. This name can also be used to access the registered - * {@link ChannelHandler} from the {@link ChannelPipeline}. - */ - String name(); - - /** - * The {@link ChannelHandler} that is bound this {@link ChannelHandlerContext}. - */ - ChannelHandler handler(); - - /** - * Return {@code true} if the {@link ChannelHandler} which belongs to this {@link ChannelHandler} was removed - * from the {@link ChannelPipeline}. Note that this method is only meant to be called from with in the - * {@link EventLoop}. - */ - boolean isRemoved(); - - /** - * A {@link Channel} was registered to its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelRegistered(); - - /** - * A {@link Channel} was unregistered from its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelUnregistered(); - - /** - * A {@link Channel} is active now, which means it is connected. - * - * This will result in having the {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelActive(); - - /** - * A {@link Channel} is inactive now, which means it is closed. - * - * This will result in having the {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelInactive(); - - /** - * A {@link Channel} received an {@link Throwable} in one of its inbound operations. - * - * This will result in having the {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireExceptionCaught(Throwable cause); - - /** - * A {@link Channel} received an user defined event. - * - * This will result in having the {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireUserEventTriggered(Object event); - - /** - * A {@link Channel} received a message. - * - * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelRead(Object msg); - - /** - * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelHandlerContext fireChannelReadComplete(); - - /** - * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelHandlerContext fireChannelWritabilityChanged(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(); - - /** - * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(); - - /** - * Request to deregister from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - * - */ - ChannelFuture deregister(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelFuture} will be notified. - * - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified and also returned. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(ChannelPromise promise); - - /** - * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(ChannelPromise promise); - - /** - * Request to deregister from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture deregister(ChannelPromise promise); - - /** - * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an - * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was - * read, and triggers a - * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the - * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. - *

- * This will result in having the - * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext read(); - - /** - * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg); - - /** - * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg, ChannelPromise promise); - - /** - * Request to flush all pending messages via this ChannelOutboundInvoker. - */ - ChannelHandlerContext flush(); - - /** - * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); - - /** - * Shortcut for call {@link #write(Object)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg); - - /** - * Return the assigned {@link ChannelPipeline} - */ - ChannelPipeline pipeline(); - - /** - * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. - */ - ByteBufAllocator alloc(); - - /** - * Return a new {@link ChannelPromise}. - */ - ChannelPromise newPromise(); - - /** - * Return an new {@link ChannelProgressivePromise} - */ -// ChannelProgressivePromise newProgressivePromise(); - - /** - * Create a new {@link ChannelFuture} which is marked as succeeded already. So {@link ChannelFuture#isSuccess()} - * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newSucceededFuture(); - - /** - * Create a new {@link ChannelFuture} which is marked as failed already. So {@link ChannelFuture#isSuccess()} - * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newFailedFuture(Throwable cause); - - /** - * Return a special ChannelPromise which can be reused for different operations. - *

- * It's only supported to use - * it for {@link ChannelHandlerContext#write(Object, ChannelPromise)}. - *

- *

- * Be aware that the returned {@link ChannelPromise} will not support most operations and should only be used - * if you want to save an object allocation for every write operation. You will not be able to detect if the - * operation was complete, only if it failed as the implementation will call - * {@link ChannelPipeline#fireExceptionCaught(Throwable)} in this case. - *

- * Be aware this is an expert feature and should be used with care! - */ - ChannelPromise voidPromise(); - -} diff --git a/java/src/game/net/channel/ChannelInboundHandler.java b/java/src/game/net/channel/ChannelInboundHandler.java deleted file mode 100644 index f66014d..0000000 --- a/java/src/game/net/channel/ChannelInboundHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * {@link ChannelHandler} which adds callbacks for state changes. This allows the user - * to hook in to state changes easily. - */ -public interface ChannelInboundHandler extends ChannelHandler { - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} was registered with its {@link EventLoop} - */ - void channelRegistered(ChannelHandlerContext ctx) throws Exception; - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} was unregistered from its {@link EventLoop} - */ - void channelUnregistered(ChannelHandlerContext ctx) throws Exception; - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} is now active - */ - void channelActive(ChannelHandlerContext ctx) throws Exception; - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} was registered is now inactive and reached its - * end of lifetime. - */ - void channelInactive(ChannelHandlerContext ctx) throws Exception; - - /** - * Invoked when the current {@link Channel} has read a message from the peer. - */ - void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception; - - /** - * Invoked when the last message read by the current read operation has been consumed by - * {@link #channelRead(ChannelHandlerContext, Object)}. If {@link ChannelOption#AUTO_READ} is off, no further - * attempt to read an inbound data from the current {@link Channel} will be made until - * {@link ChannelHandlerContext#read()} is called. - */ - void channelReadComplete(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called if an user event was triggered. - */ - void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception; - - /** - * Gets called once the writable state of a {@link Channel} changed. You can check the state with - * {@link Channel#isWritable()}. - */ - void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called if a {@link Throwable} was thrown. - */ - @Override - void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception; -} diff --git a/java/src/game/net/channel/ChannelInboundHandlerAdapter.java b/java/src/game/net/channel/ChannelInboundHandlerAdapter.java deleted file mode 100644 index 3d6f669..0000000 --- a/java/src/game/net/channel/ChannelInboundHandlerAdapter.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * Abstract base class for {@link ChannelInboundHandler} implementations which provide - * implementations of all of their methods. - * - *

- * This implementation just forward the operation to the next {@link ChannelHandler} in the - * {@link ChannelPipeline}. Sub-classes may override a method implementation to change this. - *

- *

- * Be aware that messages are not released after the {@link #channelRead(ChannelHandlerContext, Object)} - * method returns automatically. If you are looking for a {@link ChannelInboundHandler} implementation that - * releases the received messages automatically, please see {@link SimpleChannelInboundHandler}. - *

- */ -public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler { - - /** - * Calls {@link ChannelHandlerContext#fireChannelRegistered()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelRegistered(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelUnregistered()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelUnregistered(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelActive()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelActive(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelInactive(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelRead(Object)} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - ctx.fireChannelRead(msg); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelReadComplete()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelReadComplete(); - } - - /** - * Calls {@link ChannelHandlerContext#fireUserEventTriggered(Object)} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - ctx.fireUserEventTriggered(evt); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelWritabilityChanged()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelWritabilityChanged(); - } - - /** - * Calls {@link ChannelHandlerContext#fireExceptionCaught(Throwable)} to forward - * to the next {@link ChannelHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) - throws Exception { - ctx.fireExceptionCaught(cause); - } -} diff --git a/java/src/game/net/channel/ChannelInitializer.java b/java/src/game/net/channel/ChannelInitializer.java deleted file mode 100644 index 4b01276..0000000 --- a/java/src/game/net/channel/ChannelInitializer.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.channel.ChannelHandler.Sharable; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A special {@link ChannelInboundHandler} which offers an easy way to initialize a {@link Channel} once it was - * registered to its {@link EventLoop}. - * - * Implementations are most often used in the context of {@link Bootstrap#handler(ChannelHandler)} , - * {@link ServerBootstrap#handler(ChannelHandler)} and {@link ServerBootstrap#childHandler(ChannelHandler)} to - * setup the {@link ChannelPipeline} of a {@link Channel}. - * - *
- *
- * public class MyChannelInitializer extends {@link ChannelInitializer} {
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("myHandler", new MyHandler());
- *     }
- * }
- *
- * {@link ServerBootstrap} bootstrap = ...;
- * ...
- * bootstrap.childHandler(new MyChannelInitializer());
- * ...
- * 
- * Be aware that this class is marked as {@link Sharable} and so the implementation must be safe to be re-used. - * - * @param A sub-type of {@link Channel} - */ -@Sharable -public abstract class ChannelInitializer extends ChannelInboundHandlerAdapter { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelInitializer.class); - - /** - * This method will be called once the {@link Channel} was registered. After the method returns this instance - * will be removed from the {@link ChannelPipeline} of the {@link Channel}. - * - * @param ch the {@link Channel} which was registered. - * @throws Exception is thrown if an error occurs. In that case the {@link Channel} will be closed. - */ - protected abstract void initChannel(C ch) throws Exception; - - @Override - - public final void channelRegistered(ChannelHandlerContext ctx) throws Exception { - ChannelPipeline pipeline = ctx.pipeline(); - boolean success = false; - try { - initChannel((C) ctx.channel()); - pipeline.remove(this); - ctx.fireChannelRegistered(); - success = true; - } catch (Throwable t) { - logger.warn("Failed to initialize a channel. Closing: " + ctx.channel(), t); - } finally { - if (pipeline.context(this) != null) { - pipeline.remove(this); - } - if (!success) { - ctx.close(); - } - } - } -} diff --git a/java/src/game/net/channel/ChannelMetadata.java b/java/src/game/net/channel/ChannelMetadata.java deleted file mode 100644 index 5a70e69..0000000 --- a/java/src/game/net/channel/ChannelMetadata.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * Represents the properties of a {@link Channel} implementation. - */ -public final class ChannelMetadata { - - private final boolean hasDisconnect; - - /** - * Create a new instance - * - * @param hasDisconnect {@code true} if and only if the channel has the {@code disconnect()} operation - * that allows a user to disconnect and then call {@link Channel#connect(SocketAddress)} - * again, such as UDP/IP. - */ - public ChannelMetadata(boolean hasDisconnect) { - this.hasDisconnect = hasDisconnect; - } - - /** - * Returns {@code true} if and only if the channel has the {@code disconnect()} operation - * that allows a user to disconnect and then call {@link Channel#connect(SocketAddress)} again, - * such as UDP/IP. - */ - public boolean hasDisconnect() { - return hasDisconnect; - } -} diff --git a/java/src/game/net/channel/ChannelOption.java b/java/src/game/net/channel/ChannelOption.java deleted file mode 100644 index e1597a6..0000000 --- a/java/src/game/net/channel/ChannelOption.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.concurrent.ConcurrentMap; - -import game.net.buffer.ByteBufAllocator; -import game.net.util.UniqueName; -import game.net.util.internal.PlatformDependent; - -/** - * A {@link ChannelOption} allows to configure a {@link ChannelConfig} in a type-safe - * way. Which {@link ChannelOption} is supported depends on the actual implementation - * of {@link ChannelConfig} and may depend on the nature of the transport it belongs - * to. - * - * @param the type of the value which is valid for the {@link ChannelOption} - */ - -public class ChannelOption extends UniqueName { - - private static final ConcurrentMap names = PlatformDependent.newConcurrentHashMap(); - - public static final ChannelOption ALLOCATOR = valueOf("ALLOCATOR"); - public static final ChannelOption RCVBUF_ALLOCATOR = valueOf("RCVBUF_ALLOCATOR"); - public static final ChannelOption MESSAGE_SIZE_ESTIMATOR = valueOf("MESSAGE_SIZE_ESTIMATOR"); - - public static final ChannelOption CONNECT_TIMEOUT_MILLIS = valueOf("CONNECT_TIMEOUT_MILLIS"); - public static final ChannelOption MAX_MESSAGES_PER_READ = valueOf("MAX_MESSAGES_PER_READ"); - public static final ChannelOption WRITE_SPIN_COUNT = valueOf("WRITE_SPIN_COUNT"); - public static final ChannelOption WRITE_BUFFER_HIGH_WATER_MARK = valueOf("WRITE_BUFFER_HIGH_WATER_MARK"); - public static final ChannelOption WRITE_BUFFER_LOW_WATER_MARK = valueOf("WRITE_BUFFER_LOW_WATER_MARK"); - - public static final ChannelOption ALLOW_HALF_CLOSURE = valueOf("ALLOW_HALF_CLOSURE"); - public static final ChannelOption AUTO_READ = valueOf("AUTO_READ"); - - /** - * @deprecated From version 5.0, {@link Channel} will not be closed on write failure. - * - * {@code true} if and only if the {@link Channel} is closed automatically and immediately on write failure. - * The default is {@code false}. - */ - @Deprecated - public static final ChannelOption AUTO_CLOSE = valueOf("AUTO_CLOSE"); - - public static final ChannelOption SO_BROADCAST = valueOf("SO_BROADCAST"); - public static final ChannelOption SO_KEEPALIVE = valueOf("SO_KEEPALIVE"); - public static final ChannelOption SO_SNDBUF = valueOf("SO_SNDBUF"); - public static final ChannelOption SO_RCVBUF = valueOf("SO_RCVBUF"); - public static final ChannelOption SO_REUSEADDR = valueOf("SO_REUSEADDR"); - public static final ChannelOption SO_LINGER = valueOf("SO_LINGER"); - public static final ChannelOption SO_BACKLOG = valueOf("SO_BACKLOG"); - public static final ChannelOption SO_TIMEOUT = valueOf("SO_TIMEOUT"); - - public static final ChannelOption IP_TOS = valueOf("IP_TOS"); - public static final ChannelOption IP_MULTICAST_ADDR = valueOf("IP_MULTICAST_ADDR"); - public static final ChannelOption IP_MULTICAST_IF = valueOf("IP_MULTICAST_IF"); - public static final ChannelOption IP_MULTICAST_TTL = valueOf("IP_MULTICAST_TTL"); - public static final ChannelOption IP_MULTICAST_LOOP_DISABLED = valueOf("IP_MULTICAST_LOOP_DISABLED"); - - public static final ChannelOption TCP_NODELAY = valueOf("TCP_NODELAY"); - - @Deprecated - public static final ChannelOption AIO_READ_TIMEOUT = valueOf("AIO_READ_TIMEOUT"); - @Deprecated - public static final ChannelOption AIO_WRITE_TIMEOUT = valueOf("AIO_WRITE_TIMEOUT"); - - @Deprecated - public static final ChannelOption DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION = - valueOf("DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION"); - - /** - * Creates a new {@link ChannelOption} with the specified {@code name}. - */ - public static ChannelOption valueOf(String name) { - return new ChannelOption(name); - } - - /** - * @deprecated Use {@link #valueOf(String)} instead. - */ - @Deprecated - protected ChannelOption(String name) { - super(names, name); - } - - /** - * Validate the value which is set for the {@link ChannelOption}. Sub-classes - * may override this for special checks. - */ - public void validate(T value) { - if (value == null) { - throw new NullPointerException("value"); - } - } -} diff --git a/java/src/game/net/channel/ChannelOutboundBuffer.java b/java/src/game/net/channel/ChannelOutboundBuffer.java deleted file mode 100644 index 2f73d10..0000000 --- a/java/src/game/net/channel/ChannelOutboundBuffer.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; - -import game.net.buffer.ByteBuf; -import game.net.buffer.Unpooled; -import game.net.util.Recycler; -import game.net.util.Recycler.Handle; -import game.net.util.ReferenceCountUtil; -import game.net.util.concurrent.FastThreadLocal; -import game.net.util.internal.InternalThreadLocalMap; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * (Transport implementors only) an internal data structure used by {@link AbstractChannel} to store its pending - * outbound write requests. - * - * All the methods should only be called by the {@link EventLoop} of the {@link Channel}. - */ -public final class ChannelOutboundBuffer { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelOutboundBuffer.class); - - private static final FastThreadLocal NIO_BUFFERS = new FastThreadLocal() { - @Override - protected ByteBuffer[] initialValue() throws Exception { - return new ByteBuffer[1024]; - } - }; - - private final Channel channel; - - // Entry(flushedEntry) --> ... Entry(unflushedEntry) --> ... Entry(tailEntry) - // - // The Entry that is the first in the linked-list structure that was flushed - private Entry flushedEntry; - // The Entry which is the first unflushed in the linked-list structure - private Entry unflushedEntry; - // The Entry which represents the tail of the buffer - private Entry tailEntry; - // The number of flushed entries that are not written yet - private int flushed; - - private int nioBufferCount; - private long nioBufferSize; - - private boolean inFail; - - private static final AtomicLongFieldUpdater TOTAL_PENDING_SIZE_UPDATER; - - - private volatile long totalPendingSize; - - private static final AtomicIntegerFieldUpdater WRITABLE_UPDATER; - - - private volatile int writable = 1; - - static { - AtomicIntegerFieldUpdater writableUpdater = - PlatformDependent.newAtomicIntegerFieldUpdater(ChannelOutboundBuffer.class, "writable"); - if (writableUpdater == null) { - writableUpdater = AtomicIntegerFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "writable"); - } - WRITABLE_UPDATER = writableUpdater; - - AtomicLongFieldUpdater pendingSizeUpdater = - PlatformDependent.newAtomicLongFieldUpdater(ChannelOutboundBuffer.class, "totalPendingSize"); - if (pendingSizeUpdater == null) { - pendingSizeUpdater = AtomicLongFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "totalPendingSize"); - } - TOTAL_PENDING_SIZE_UPDATER = pendingSizeUpdater; - } - - ChannelOutboundBuffer(AbstractChannel channel) { - this.channel = channel; - } - - /** - * Add given message to this {@link ChannelOutboundBuffer}. The given {@link ChannelPromise} will be notified once - * the message was written. - */ - public void addMessage(Object msg, int size, ChannelPromise promise) { - Entry entry = Entry.newInstance(msg, size, total(msg), promise); - if (tailEntry == null) { - flushedEntry = null; - tailEntry = entry; - } else { - Entry tail = tailEntry; - tail.next = entry; - tailEntry = entry; - } - if (unflushedEntry == null) { - unflushedEntry = entry; - } - - // increment pending bytes after adding message to the unflushed arrays. - // See https://github.com/netty/netty/issues/1619 - incrementPendingOutboundBytes(size); - } - - /** - * Add a flush to this {@link ChannelOutboundBuffer}. This means all previous added messages are marked as flushed - * and so you will be able to handle them. - */ - public void addFlush() { - // There is no need to process all entries if there was already a flush before and no new messages - // where added in the meantime. - // - // See https://github.com/netty/netty/issues/2577 - Entry entry = unflushedEntry; - if (entry != null) { - if (flushedEntry == null) { - // there is no flushedEntry yet, so start with the entry - flushedEntry = entry; - } - do { - flushed ++; - if (!entry.promise.setUncancellable()) { - // Was cancelled so make sure we free up memory and notify about the freed bytes - int pending = entry.cancel(); - decrementPendingOutboundBytes(pending); - } - entry = entry.next; - } while (entry != null); - - // All flushed so reset unflushedEntry - unflushedEntry = null; - } - } - - /** - * Increment the pending bytes which will be written at some point. - * This method is thread-safe! - */ - void incrementPendingOutboundBytes(long size) { - if (size == 0) { - return; - } - - long newWriteBufferSize = TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, size); - if (newWriteBufferSize > channel.config().getWriteBufferHighWaterMark()) { - if (WRITABLE_UPDATER.compareAndSet(this, 1, 0)) { - channel.pipeline().fireChannelWritabilityChanged(); - } - } - } - - /** - * Decrement the pending bytes which will be written at some point. - * This method is thread-safe! - */ - void decrementPendingOutboundBytes(long size) { - if (size == 0) { - return; - } - - long newWriteBufferSize = TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, -size); - if (newWriteBufferSize == 0 || newWriteBufferSize < channel.config().getWriteBufferLowWaterMark()) { - if (WRITABLE_UPDATER.compareAndSet(this, 0, 1)) { - channel.pipeline().fireChannelWritabilityChanged(); - } - } - } - - private static long total(Object msg) { - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).readableBytes(); - } -// if (msg instanceof FileRegion) { -// return ((FileRegion) msg).count(); -// } -// if (msg instanceof ByteBufHolder) { -// return ((ByteBufHolder) msg).content().readableBytes(); -// } - return -1; - } - - /** - * Return the current message to write or {@code null} if nothing was flushed before and so is ready to be written. - */ - public Object current() { - Entry entry = flushedEntry; - if (entry == null) { - return null; - } - - return entry.msg; - } - - /** - * Notify the {@link ChannelPromise} of the current message about writing progress. - */ - public void progress(long amount) { - Entry e = flushedEntry; - assert e != null; - ChannelPromise p = e.promise; - if (p instanceof ChannelProgressivePromise) { - long progress = e.progress + amount; - e.progress = progress; - ((ChannelProgressivePromise) p).tryProgress(progress, e.total); - } - } - - /** - * Will remove the current message, mark its {@link ChannelPromise} as success and return {@code true}. If no - * flushed message exists at the time this method is called it will return {@code false} to signal that no more - * messages are ready to be handled. - */ - public boolean remove() { - Entry e = flushedEntry; - if (e == null) { - return false; - } - Object msg = e.msg; - - ChannelPromise promise = e.promise; - int size = e.pendingSize; - - removeEntry(e); - - if (!e.cancelled) { - // only release message, notify and decrement if it was not canceled before. - ReferenceCountUtil.safeRelease(msg); - safeSuccess(promise); - decrementPendingOutboundBytes(size); - } - - // recycle the entry - e.recycle(); - - return true; - } - - /** - * Will remove the current message, mark its {@link ChannelPromise} as failure using the given {@link Throwable} - * and return {@code true}. If no flushed message exists at the time this method is called it will return - * {@code false} to signal that no more messages are ready to be handled. - */ - public boolean remove(Throwable cause) { - Entry e = flushedEntry; - if (e == null) { - return false; - } - Object msg = e.msg; - - ChannelPromise promise = e.promise; - int size = e.pendingSize; - - removeEntry(e); - - if (!e.cancelled) { - // only release message, fail and decrement if it was not canceled before. - ReferenceCountUtil.safeRelease(msg); - - safeFail(promise, cause); - decrementPendingOutboundBytes(size); - } - - // recycle the entry - e.recycle(); - - return true; - } - - private void removeEntry(Entry e) { - if (-- flushed == 0) { - // processed everything - flushedEntry = null; - if (e == tailEntry) { - tailEntry = null; - unflushedEntry = null; - } - } else { - flushedEntry = e.next; - } - } - - /** - * Removes the fully written entries and update the reader index of the partially written entry. - * This operation assumes all messages in this buffer is {@link ByteBuf}. - */ - public void removeBytes(long writtenBytes) { - for (;;) { - Object msg = current(); - if (!(msg instanceof ByteBuf)) { - assert writtenBytes == 0; - break; - } - - final ByteBuf buf = (ByteBuf) msg; - final int readerIndex = buf.readerIndex(); - final int readableBytes = buf.writerIndex() - readerIndex; - - if (readableBytes <= writtenBytes) { - if (writtenBytes != 0) { - progress(readableBytes); - writtenBytes -= readableBytes; - } - remove(); - } else { // readableBytes > writtenBytes - if (writtenBytes != 0) { - buf.readerIndex(readerIndex + (int) writtenBytes); - progress(writtenBytes); - } - break; - } - } - } - - /** - * Returns an array of direct NIO buffers if the currently pending messages are made of {@link ByteBuf} only. - * {@link #nioBufferCount()} and {@link #nioBufferSize()} will return the number of NIO buffers in the returned - * array and the total number of readable bytes of the NIO buffers respectively. - *

- * Note that the returned array is reused and thus should not escape - * {@link AbstractChannel#doWrite(ChannelOutboundBuffer)}. - * Refer to {@link NioSocketChannel#doWrite(ChannelOutboundBuffer)} for an example. - *

- */ - public ByteBuffer[] nioBuffers() { - long nioBufferSize = 0; - int nioBufferCount = 0; - final InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get(); - ByteBuffer[] nioBuffers = NIO_BUFFERS.get(threadLocalMap); - Entry entry = flushedEntry; - while (isFlushedEntry(entry) && entry.msg instanceof ByteBuf) { - if (!entry.cancelled) { - ByteBuf buf = (ByteBuf) entry.msg; - final int readerIndex = buf.readerIndex(); - final int readableBytes = buf.writerIndex() - readerIndex; - - if (readableBytes > 0) { - nioBufferSize += readableBytes; - int count = entry.count; - if (count == -1) { - //noinspection ConstantValueVariableUse - entry.count = count = buf.nioBufferCount(); - } - int neededSpace = nioBufferCount + count; - if (neededSpace > nioBuffers.length) { - nioBuffers = expandNioBufferArray(nioBuffers, neededSpace, nioBufferCount); - NIO_BUFFERS.set(threadLocalMap, nioBuffers); - } - if (count == 1) { - ByteBuffer nioBuf = entry.buf; - if (nioBuf == null) { - // cache ByteBuffer as it may need to create a new ByteBuffer instance if its a - // derived buffer - entry.buf = nioBuf = buf.internalNioBuffer(readerIndex, readableBytes); - } - nioBuffers[nioBufferCount ++] = nioBuf; - } else { - ByteBuffer[] nioBufs = entry.bufs; - if (nioBufs == null) { - // cached ByteBuffers as they may be expensive to create in terms - // of Object allocation - entry.bufs = nioBufs = buf.nioBuffers(); - } - nioBufferCount = fillBufferArray(nioBufs, nioBuffers, nioBufferCount); - } - } - } - entry = entry.next; - } - this.nioBufferCount = nioBufferCount; - this.nioBufferSize = nioBufferSize; - - return nioBuffers; - } - - private static int fillBufferArray(ByteBuffer[] nioBufs, ByteBuffer[] nioBuffers, int nioBufferCount) { - for (ByteBuffer nioBuf: nioBufs) { - if (nioBuf == null) { - break; - } - nioBuffers[nioBufferCount ++] = nioBuf; - } - return nioBufferCount; - } - - private static ByteBuffer[] expandNioBufferArray(ByteBuffer[] array, int neededSpace, int size) { - int newCapacity = array.length; - do { - // double capacity until it is big enough - // See https://github.com/netty/netty/issues/1890 - newCapacity <<= 1; - - if (newCapacity < 0) { - throw new IllegalStateException(); - } - - } while (neededSpace > newCapacity); - - ByteBuffer[] newArray = new ByteBuffer[newCapacity]; - System.arraycopy(array, 0, newArray, 0, size); - - return newArray; - } - - /** - * Returns the number of {@link ByteBuffer} that can be written out of the {@link ByteBuffer} array that was - * obtained via {@link #nioBuffers()}. This method MUST be called after {@link #nioBuffers()} - * was called. - */ - public int nioBufferCount() { - return nioBufferCount; - } - - /** - * Returns the number of bytes that can be written out of the {@link ByteBuffer} array that was - * obtained via {@link #nioBuffers()}. This method MUST be called after {@link #nioBuffers()} - * was called. - */ - public long nioBufferSize() { - return nioBufferSize; - } - - boolean isWritable() { - return writable != 0; - } - - /** - * Returns the number of flushed messages in this {@link ChannelOutboundBuffer}. - */ - public int size() { - return flushed; - } - - /** - * Returns {@code true} if there are flushed messages in this {@link ChannelOutboundBuffer} or {@code false} - * otherwise. - */ - public boolean isEmpty() { - return flushed == 0; - } - - void failFlushed(Throwable cause) { - // Make sure that this method does not reenter. A listener added to the current promise can be notified by the - // current thread in the tryFailure() call of the loop below, and the listener can trigger another fail() call - // indirectly (usually by closing the channel.) - // - // See https://github.com/netty/netty/issues/1501 - if (inFail) { - return; - } - - try { - inFail = true; - for (;;) { - if (!remove(cause)) { - break; - } - } - } finally { - inFail = false; - } - } - - void close(final ClosedChannelException cause) { - if (inFail) { - channel.eventLoop().execute(new Runnable() { - @Override - public void run() { - close(cause); - } - }); - return; - } - - inFail = true; - - if (channel.isOpen()) { - throw new IllegalStateException("close() must be invoked after the channel is closed."); - } - - if (!isEmpty()) { - throw new IllegalStateException("close() must be invoked after all flushed writes are handled."); - } - - // Release all unflushed messages. - try { - Entry e = unflushedEntry; - while (e != null) { - // Just decrease; do not trigger any events via decrementPendingOutboundBytes() - int size = e.pendingSize; - TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, -size); - - if (!e.cancelled) { - ReferenceCountUtil.safeRelease(e.msg); - safeFail(e.promise, cause); - } - e = e.recycleAndGetNext(); - } - } finally { - inFail = false; - } - } - - private static void safeSuccess(ChannelPromise promise) { - if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) { - logger.warn("Failed to mark a promise as success because it is done already: {}", promise); - } - } - - private static void safeFail(ChannelPromise promise, Throwable cause) { - if (!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) { - logger.warn("Failed to mark a promise as failure because it's done already: {}", promise, cause); - } - } - - @Deprecated - public void recycle() { - // NOOP - } - - public long totalPendingWriteBytes() { - return totalPendingSize; - } - - /** - * Call {@link MessageProcessor#processMessage(Object)} for each flushed message - * in this {@link ChannelOutboundBuffer} until {@link MessageProcessor#processMessage(Object)} - * returns {@code false} or there are no more flushed messages to process. - */ - public void forEachFlushedMessage(MessageProcessor processor) throws Exception { - if (processor == null) { - throw new NullPointerException("processor"); - } - - Entry entry = flushedEntry; - if (entry == null) { - return; - } - - do { - if (!entry.cancelled) { - if (!processor.processMessage(entry.msg)) { - return; - } - } - entry = entry.next; - } while (isFlushedEntry(entry)); - } - - private boolean isFlushedEntry(Entry e) { - return e != null && e != unflushedEntry; - } - - public interface MessageProcessor { - /** - * Will be called for each flushed message until it either there are no more flushed messages or this - * method returns {@code false}. - */ - boolean processMessage(Object msg) throws Exception; - } - - static final class Entry { - private static final Recycler RECYCLER = new Recycler() { - @Override - protected Entry newObject(Handle handle) { - return new Entry(handle); - } - }; - - private final Handle handle; - Entry next; - Object msg; - ByteBuffer[] bufs; - ByteBuffer buf; - ChannelPromise promise; - long progress; - long total; - int pendingSize; - int count = -1; - boolean cancelled; - - private Entry(Handle handle) { - this.handle = handle; - } - - static Entry newInstance(Object msg, int size, long total, ChannelPromise promise) { - Entry entry = RECYCLER.get(); - entry.msg = msg; - entry.pendingSize = size; - entry.total = total; - entry.promise = promise; - return entry; - } - - int cancel() { - if (!cancelled) { - cancelled = true; - int pSize = pendingSize; - - // release message and replace with an empty buffer - ReferenceCountUtil.safeRelease(msg); - msg = Unpooled.EMPTY_BUFFER; - - pendingSize = 0; - total = 0; - progress = 0; - bufs = null; - buf = null; - return pSize; - } - return 0; - } - - void recycle() { - next = null; - bufs = null; - buf = null; - msg = null; - promise = null; - progress = 0; - total = 0; - pendingSize = 0; - count = -1; - cancelled = false; - RECYCLER.recycle(this, handle); - } - - Entry recycleAndGetNext() { - Entry next = this.next; - recycle(); - return next; - } - } -} diff --git a/java/src/game/net/channel/ChannelOutboundHandler.java b/java/src/game/net/channel/ChannelOutboundHandler.java deleted file mode 100644 index 5b5c748..0000000 --- a/java/src/game/net/channel/ChannelOutboundHandler.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.SocketAddress; - -/** - * {@link ChannelHandler} which will get notified for IO-outbound-operations. - */ -public interface ChannelOutboundHandler extends ChannelHandler { - /** - * Called once a bind operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the bind operation is made - * @param localAddress the {@link SocketAddress} to which it should bound - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception; - - /** - * Called once a connect operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the connect operation is made - * @param remoteAddress the {@link SocketAddress} to which it should connect - * @param localAddress the {@link SocketAddress} which is used as source on connect - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void connect( - ChannelHandlerContext ctx, SocketAddress remoteAddress, - SocketAddress localAddress, ChannelPromise promise) throws Exception; - - /** - * Called once a disconnect operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the disconnect operation is made - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception; - - /** - * Called once a close operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the close operation is made - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception; - - /** - * Called once a deregister operation is made from the current registered {@link EventLoop}. - * - * @param ctx the {@link ChannelHandlerContext} for which the close operation is made - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception; - - /** - * Intercepts {@link ChannelHandlerContext#read()}. - */ - void read(ChannelHandlerContext ctx) throws Exception; - - /** - * Called once a write operation is made. The write operation will write the messages through the - * {@link ChannelPipeline}. Those are then ready to be flushed to the actual {@link Channel} once - * {@link Channel#flush()} is called - * - * @param ctx the {@link ChannelHandlerContext} for which the write operation is made - * @param msg the message to write - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception; - - /** - * Called once a flush operation is made. The flush operation will try to flush out all previous written messages - * that are pending. - * - * @param ctx the {@link ChannelHandlerContext} for which the flush operation is made - * @throws Exception thrown if an error accour - */ - void flush(ChannelHandlerContext ctx) throws Exception; -} diff --git a/java/src/game/net/channel/ChannelOutboundHandlerAdapter.java b/java/src/game/net/channel/ChannelOutboundHandlerAdapter.java deleted file mode 100644 index 3333b8d..0000000 --- a/java/src/game/net/channel/ChannelOutboundHandlerAdapter.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.SocketAddress; - -/** - * Skelton implementation of a {@link ChannelOutboundHandler}. This implementation just forwards each method call via - * the {@link ChannelHandlerContext}. - */ -public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler { - - /** - * Calls {@link ChannelHandlerContext#bind(SocketAddress, ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, - ChannelPromise promise) throws Exception { - ctx.bind(localAddress, promise); - } - - /** - * Calls {@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, - SocketAddress localAddress, ChannelPromise promise) throws Exception { - ctx.connect(remoteAddress, localAddress, promise); - } - - /** - * Calls {@link ChannelHandlerContext#disconnect(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) - throws Exception { - ctx.disconnect(promise); - } - - /** - * Calls {@link ChannelHandlerContext#close(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise promise) - throws Exception { - ctx.close(promise); - } - - /** - * Calls {@link ChannelHandlerContext#close(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.deregister(promise); - } - - /** - * Calls {@link ChannelHandlerContext#read()} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void read(ChannelHandlerContext ctx) throws Exception { - ctx.read(); - } - - /** - * Calls {@link ChannelHandlerContext#write(Object)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - ctx.write(msg, promise); - } - - /** - * Calls {@link ChannelHandlerContext#flush()} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } -} diff --git a/java/src/game/net/channel/ChannelPipeline.java b/java/src/game/net/channel/ChannelPipeline.java deleted file mode 100644 index c09a9f2..0000000 --- a/java/src/game/net/channel/ChannelPipeline.java +++ /dev/null @@ -1,872 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.SocketAddress; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import game.net.util.concurrent.EventExecutorGroup; - - -/** - * A list of {@link ChannelHandler}s which handles or intercepts inbound events and outbound operations of a - * {@link Channel}. {@link ChannelPipeline} implements an advanced form of the - * Intercepting Filter pattern - * to give a user full control over how an event is handled and how the {@link ChannelHandler}s in a pipeline - * interact with each other. - * - *

Creation of a pipeline

- * - * Each channel has its own pipeline and it is created automatically when a new channel is created. - * - *

How an event flows in a pipeline

- * - * The following diagram describes how I/O events are processed by {@link ChannelHandler}s in a {@link ChannelPipeline} - * typically. An I/O event is handled by either a {@link ChannelInboundHandler} or a {@link ChannelOutboundHandler} - * and be forwarded to its closest handler by calling the event propagation methods defined in - * {@link ChannelHandlerContext}, such as {@link ChannelHandlerContext#fireChannelRead(Object)} and - * {@link ChannelHandlerContext#write(Object)}. - * - *
- *                                                 I/O Request
- *                                            via {@link Channel} or
- *                                        {@link ChannelHandlerContext}
- *                                                      |
- *  +---------------------------------------------------+---------------+
- *  |                           ChannelPipeline         |               |
- *  |                                                  \|/              |
- *  |    +---------------------+            +-----------+----------+    |
- *  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  |               |
- *  |               |                                  \|/              |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  .               |
- *  |               .                                   .               |
- *  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
- *  |        [ method call]                       [method call]         |
- *  |               .                                   .               |
- *  |               .                                  \|/              |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  |               |
- *  |               |                                  \|/              |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  |               |
- *  +---------------+-----------------------------------+---------------+
- *                  |                                  \|/
- *  +---------------+-----------------------------------+---------------+
- *  |               |                                   |               |
- *  |       [ Socket.read() ]                    [ Socket.write() ]     |
- *  |                                                                   |
- *  |  Netty Internal I/O Threads (Transport Implementation)            |
- *  +-------------------------------------------------------------------+
- * 
- * An inbound event is handled by the inbound handlers in the bottom-up direction as shown on the left side of the - * diagram. An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the - * diagram. The inbound data is often read from a remote peer via the actual input operation such as - * {@link SocketChannel#read(ByteBuffer)}. If an inbound event goes beyond the top inbound handler, it is discarded - * silently, or logged if it needs your attention. - *

- * An outbound event is handled by the outbound handler in the top-down direction as shown on the right side of the - * diagram. An outbound handler usually generates or transforms the outbound traffic such as write requests. - * If an outbound event goes beyond the bottom outbound handler, it is handled by an I/O thread associated with the - * {@link Channel}. The I/O thread often performs the actual output operation such as - * {@link SocketChannel#write(ByteBuffer)}. - *

- * For example, let us assume that we created the following pipeline: - *

- * {@link ChannelPipeline} p = ...;
- * p.addLast("1", new InboundHandlerA());
- * p.addLast("2", new InboundHandlerB());
- * p.addLast("3", new OutboundHandlerA());
- * p.addLast("4", new OutboundHandlerB());
- * p.addLast("5", new InboundOutboundHandlerX());
- * 
- * In the example above, the class whose name starts with {@code Inbound} means it is an inbound handler. - * The class whose name starts with {@code Outbound} means it is a outbound handler. - *

- * In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound. - * When an event goes outbound, the order is 5, 4, 3, 2, 1. On top of this principle, {@link ChannelPipeline} skips - * the evaluation of certain handlers to shorten the stack depth: - *

    - *
  • 3 and 4 don't implement {@link ChannelInboundHandler}, and therefore the actual evaluation order of an inbound - * event will be: 1, 2, and 5.
  • - *
  • 1 and 2 don't implement {@link ChannelOutboundHandler}, and therefore the actual evaluation order of a - * outbound event will be: 5, 4, and 3.
  • - *
  • If 5 implements both {@link ChannelInboundHandler} and {@link ChannelOutboundHandler}, the evaluation order of - * an inbound and a outbound event could be 125 and 543 respectively.
  • - *
- * - *

Forwarding an event to the next handler

- * - * As you might noticed in the diagram shows, a handler has to invoke the event propagation methods in - * {@link ChannelHandlerContext} to forward an event to its next handler. Those methods include: - *
    - *
  • Inbound event propagation methods: - *
      - *
    • {@link ChannelHandlerContext#fireChannelRegistered()}
    • - *
    • {@link ChannelHandlerContext#fireChannelActive()}
    • - *
    • {@link ChannelHandlerContext#fireChannelRead(Object)}
    • - *
    • {@link ChannelHandlerContext#fireChannelReadComplete()}
    • - *
    • {@link ChannelHandlerContext#fireExceptionCaught(Throwable)}
    • - *
    • {@link ChannelHandlerContext#fireUserEventTriggered(Object)}
    • - *
    • {@link ChannelHandlerContext#fireChannelWritabilityChanged()}
    • - *
    • {@link ChannelHandlerContext#fireChannelInactive()}
    • - *
    • {@link ChannelHandlerContext#fireChannelUnregistered()}
    • - *
    - *
  • - *
  • Outbound event propagation methods: - *
      - *
    • {@link ChannelHandlerContext#bind(SocketAddress, ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#write(Object, ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#flush()}
    • - *
    • {@link ChannelHandlerContext#read()}
    • - *
    • {@link ChannelHandlerContext#disconnect(ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#close(ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#deregister(ChannelPromise)}
    • - *
    - *
  • - *
- * - * and the following example shows how the event propagation is usually done: - * - *
- * public class MyInboundHandler extends {@link ChannelInboundHandlerAdapter} {
- *     {@code @Override}
- *     public void channelActive({@link ChannelHandlerContext} ctx) {
- *         System.out.println("Connected!");
- *         ctx.fireChannelActive();
- *     }
- * }
- *
- * public clas MyOutboundHandler extends {@link ChannelOutboundHandlerAdapter} {
- *     {@code @Override}
- *     public void close({@link ChannelHandlerContext} ctx, {@link ChannelPromise} promise) {
- *         System.out.println("Closing ..");
- *         ctx.close(promise);
- *     }
- * }
- * 
- * - *

Building a pipeline

- *

- * A user is supposed to have one or more {@link ChannelHandler}s in a pipeline to receive I/O events (e.g. read) and - * to request I/O operations (e.g. write and close). For example, a typical server will have the following handlers - * in each channel's pipeline, but your mileage may vary depending on the complexity and characteristics of the - * protocol and business logic: - * - *

    - *
  1. Protocol Decoder - translates binary data (e.g. {@link ByteBuf}) into a Java object.
  2. - *
  3. Protocol Encoder - translates a Java object into binary data.
  4. - *
  5. Business Logic Handler - performs the actual business logic (e.g. database access).
  6. - *
- * - * and it could be represented as shown in the following example: - * - *
- * static final {@link EventExecutorGroup} group = new {@link DefaultEventExecutorGroup}(16);
- * ...
- *
- * {@link ChannelPipeline} pipeline = ch.pipeline();
- *
- * pipeline.addLast("decoder", new MyProtocolDecoder());
- * pipeline.addLast("encoder", new MyProtocolEncoder());
- *
- * // Tell the pipeline to run MyBusinessLogicHandler's event handler methods
- * // in a different thread than an I/O thread so that the I/O thread is not blocked by
- * // a time-consuming task.
- * // If your business logic is fully asynchronous or finished very quickly, you don't
- * // need to specify a group.
- * pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
- * 
- * - *

Thread safety

- *

- * A {@link ChannelHandler} can be added or removed at any time because a {@link ChannelPipeline} is thread safe. - * For example, you can insert an encryption handler when sensitive information is about to be exchanged, and remove it - * after the exchange. - */ -public interface ChannelPipeline - extends Iterable> { - - /** - * Inserts a {@link ChannelHandler} at the first position of this pipeline. - * - * @param name the name of the handler to insert first - * @param handler the handler to insert first - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addFirst(String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} at the first position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param name the name of the handler to insert first - * @param handler the handler to insert first - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler); - - /** - * Appends a {@link ChannelHandler} at the last position of this pipeline. - * - * @param name the name of the handler to append - * @param handler the handler to append - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addLast(String name, ChannelHandler handler); - - /** - * Appends a {@link ChannelHandler} at the last position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param name the name of the handler to append - * @param handler the handler to append - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} before an existing handler of this - * pipeline. - * - * @param baseName the name of the existing handler - * @param name the name of the handler to insert before - * @param handler the handler to insert before - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} before an existing handler of this - * pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param baseName the name of the existing handler - * @param name the name of the handler to insert before - * @param handler the handler to insert before - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} after an existing handler of this - * pipeline. - * - * @param baseName the name of the existing handler - * @param name the name of the handler to insert after - * @param handler the handler to insert after - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} after an existing handler of this - * pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param baseName the name of the existing handler - * @param name the name of the handler to insert after - * @param handler the handler to insert after - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler}s at the first position of this pipeline. - * - * @param handlers the handlers to insert first - * - */ - ChannelPipeline addFirst(ChannelHandler... handlers); - - /** - * Inserts a {@link ChannelHandler}s at the first position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s - * methods. - * @param handlers the handlers to insert first - * - */ - ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler... handlers); - - /** - * Inserts a {@link ChannelHandler}s at the last position of this pipeline. - * - * @param handlers the handlers to insert last - * - */ - ChannelPipeline addLast(ChannelHandler... handlers); - - /** - * Inserts a {@link ChannelHandler}s at the last position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s - * methods. - * @param handlers the handlers to insert last - * - */ - ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler... handlers); - - /** - * Removes the specified {@link ChannelHandler} from this pipeline. - * - * @param handler the {@link ChannelHandler} to remove - * - * @throws NoSuchElementException - * if there's no such handler in this pipeline - * @throws NullPointerException - * if the specified handler is {@code null} - */ - ChannelPipeline remove(ChannelHandler handler); - - /** - * Removes the {@link ChannelHandler} with the specified name from this pipeline. - * - * @param name the name under which the {@link ChannelHandler} was stored. - * - * @return the removed handler - * - * @throws NoSuchElementException - * if there's no such handler with the specified name in this pipeline - * @throws NullPointerException - * if the specified name is {@code null} - */ - ChannelHandler remove(String name); - - /** - * Removes the {@link ChannelHandler} of the specified type from this pipeline. - * - * @param the type of the handler - * @param handlerType the type of the handler - * - * @return the removed handler - * - * @throws NoSuchElementException - * if there's no such handler of the specified type in this pipeline - * @throws NullPointerException - * if the specified handler type is {@code null} - */ - T remove(Class handlerType); - - /** - * Removes the first {@link ChannelHandler} in this pipeline. - * - * @return the removed handler - * - * @throws NoSuchElementException - * if this pipeline is empty - */ - ChannelHandler removeFirst(); - - /** - * Removes the last {@link ChannelHandler} in this pipeline. - * - * @return the removed handler - * - * @throws NoSuchElementException - * if this pipeline is empty - */ - ChannelHandler removeLast(); - - /** - * Replaces the specified {@link ChannelHandler} with a new handler in this pipeline. - * - * @param oldHandler the {@link ChannelHandler} to be replaced - * @param newName the name under which the replacement should be added - * @param newHandler the {@link ChannelHandler} which is used as replacement - * - * @return itself - - * @throws NoSuchElementException - * if the specified old handler does not exist in this pipeline - * @throws IllegalArgumentException - * if a handler with the specified new name already exists in this - * pipeline, except for the handler to be replaced - * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} - */ - ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler); - - /** - * Replaces the {@link ChannelHandler} of the specified name with a new handler in this pipeline. - * - * @param oldName the name of the {@link ChannelHandler} to be replaced - * @param newName the name under which the replacement should be added - * @param newHandler the {@link ChannelHandler} which is used as replacement - * - * @return the removed handler - * - * @throws NoSuchElementException - * if the handler with the specified old name does not exist in this pipeline - * @throws IllegalArgumentException - * if a handler with the specified new name already exists in this - * pipeline, except for the handler to be replaced - * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} - */ - ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler); - - /** - * Replaces the {@link ChannelHandler} of the specified type with a new handler in this pipeline. - * - * @param oldHandlerType the type of the handler to be removed - * @param newName the name under which the replacement should be added - * @param newHandler the {@link ChannelHandler} which is used as replacement - * - * @return the removed handler - * - * @throws NoSuchElementException - * if the handler of the specified old handler type does not exist - * in this pipeline - * @throws IllegalArgumentException - * if a handler with the specified new name already exists in this - * pipeline, except for the handler to be replaced - * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} - */ - T replace(Class oldHandlerType, String newName, - ChannelHandler newHandler); - - /** - * Returns the first {@link ChannelHandler} in this pipeline. - * - * @return the first handler. {@code null} if this pipeline is empty. - */ - ChannelHandler first(); - - /** - * Returns the context of the first {@link ChannelHandler} in this pipeline. - * - * @return the context of the first handler. {@code null} if this pipeline is empty. - */ - ChannelHandlerContext firstContext(); - - /** - * Returns the last {@link ChannelHandler} in this pipeline. - * - * @return the last handler. {@code null} if this pipeline is empty. - */ - ChannelHandler last(); - - /** - * Returns the context of the last {@link ChannelHandler} in this pipeline. - * - * @return the context of the last handler. {@code null} if this pipeline is empty. - */ - ChannelHandlerContext lastContext(); - - /** - * Returns the {@link ChannelHandler} with the specified name in this - * pipeline. - * - * @return the handler with the specified name. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandler get(String name); - - /** - * Returns the {@link ChannelHandler} of the specified type in this - * pipeline. - * - * @return the handler of the specified handler type. - * {@code null} if there's no such handler in this pipeline. - */ - T get(Class handlerType); - - /** - * Returns the context object of the specified {@link ChannelHandler} in - * this pipeline. - * - * @return the context object of the specified handler. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandlerContext context(ChannelHandler handler); - - /** - * Returns the context object of the {@link ChannelHandler} with the - * specified name in this pipeline. - * - * @return the context object of the handler with the specified name. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandlerContext context(String name); - - /** - * Returns the context object of the {@link ChannelHandler} of the - * specified type in this pipeline. - * - * @return the context object of the handler of the specified type. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandlerContext context(Class handlerType); - - /** - * Returns the {@link Channel} that this pipeline is attached to. - * - * @return the channel. {@code null} if this pipeline is not attached yet. - */ - Channel channel(); - - /** - * Returns the {@link List} of the handler names. - */ - List names(); - - /** - * Converts this pipeline into an ordered {@link Map} whose keys are - * handler names and whose values are handlers. - */ - Map toMap(); - - /** - * A {@link Channel} was registered to its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelRegistered(); - - /** - * A {@link Channel} was unregistered from its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelUnregistered(); - - /** - * A {@link Channel} is active now, which means it is connected. - * - * This will result in having the {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelActive(); - - /** - * A {@link Channel} is inactive now, which means it is closed. - * - * This will result in having the {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelInactive(); - - /** - * A {@link Channel} received an {@link Throwable} in one of its inbound operations. - * - * This will result in having the {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireExceptionCaught(Throwable cause); - - /** - * A {@link Channel} received an user defined event. - * - * This will result in having the {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireUserEventTriggered(Object event); - - /** - * A {@link Channel} received a message. - * - * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelRead(Object msg); - - /** - * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelPipeline fireChannelReadComplete(); - - /** - * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelPipeline fireChannelWritabilityChanged(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(); - - /** - * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(); - - /** - * Request to deregister the {@link Channel} from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - * - */ - ChannelFuture deregister(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelFuture} will be notified. - * - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified and also returned. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(ChannelPromise promise); - - /** - * Request to close the {@link Channel} bound to this {@link ChannelPipeline} and notify the {@link ChannelFuture} - * once the operation completes, either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(ChannelPromise promise); - - /** - * Request to deregister the {@link Channel} bound this {@link ChannelPipeline} from the previous assigned - * {@link EventExecutor} and notify the {@link ChannelFuture} once the operation completes, either because the - * operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture deregister(ChannelPromise promise); - - /** - * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an - * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was - * read, and triggers a - * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the - * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. - *

- * This will result in having the - * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline read(); - - /** - * Request to write a message via this {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg); - - /** - * Request to write a message via this {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg, ChannelPromise promise); - - /** - * Request to flush all pending messages. - */ - ChannelPipeline flush(); - - /** - * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); - - /** - * Shortcut for call {@link #write(Object)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg); -} diff --git a/java/src/game/net/channel/ChannelPipelineException.java b/java/src/game/net/channel/ChannelPipelineException.java deleted file mode 100644 index 890f028..0000000 --- a/java/src/game/net/channel/ChannelPipelineException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * A {@link ChannelException} which is thrown when a {@link ChannelPipeline} - * failed to execute an operation. - */ -public class ChannelPipelineException extends ChannelException { - - private static final long serialVersionUID = 3379174210419885980L; - - /** - * Creates a new instance. - */ - public ChannelPipelineException() { - } - - /** - * Creates a new instance. - */ - public ChannelPipelineException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public ChannelPipelineException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public ChannelPipelineException(Throwable cause) { - super(cause); - } -} diff --git a/java/src/game/net/channel/ChannelProgressivePromise.java b/java/src/game/net/channel/ChannelProgressivePromise.java deleted file mode 100644 index 87bab09..0000000 --- a/java/src/game/net/channel/ChannelProgressivePromise.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; -import game.net.util.concurrent.ProgressiveFuture; -import game.net.util.concurrent.ProgressivePromise; - -/** - * Special {@link ChannelPromise} which will be notified once the associated bytes is transferring. - */ -public interface ChannelProgressivePromise extends ProgressivePromise, ChannelFuture, ProgressiveFuture, ChannelPromise { -// @Override -// ChannelProgressiveFuture addListener(GenericFutureListener> listener); -// -// @Override -// ChannelProgressiveFuture addListeners(GenericFutureListener>... listeners); -// -// @Override -// ChannelProgressiveFuture removeListener(GenericFutureListener> listener); -// -// @Override -// ChannelProgressiveFuture removeListeners(GenericFutureListener>... listeners); -// -// @Override -// ChannelProgressiveFuture sync() throws InterruptedException; -// -// @Override -// ChannelProgressiveFuture syncUninterruptibly(); -// -// @Override -// ChannelProgressiveFuture await() throws InterruptedException; -// -// @Override -// ChannelProgressiveFuture awaitUninterruptibly(); - - @Override - ChannelProgressivePromise addListener(GenericFutureListener> listener); - - @Override - ChannelProgressivePromise addListeners(GenericFutureListener>... listeners); - - @Override - ChannelProgressivePromise removeListener(GenericFutureListener> listener); - - @Override - ChannelProgressivePromise removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelProgressivePromise sync() throws InterruptedException; - - @Override - ChannelProgressivePromise syncUninterruptibly(); - - @Override - ChannelProgressivePromise await() throws InterruptedException; - - @Override - ChannelProgressivePromise awaitUninterruptibly(); - - @Override - ChannelProgressivePromise setSuccess(Void result); - - @Override - ChannelProgressivePromise setSuccess(); - - @Override - ChannelProgressivePromise setFailure(Throwable cause); - - @Override - ChannelProgressivePromise setProgress(long progress, long total); -} diff --git a/java/src/game/net/channel/ChannelPromise.java b/java/src/game/net/channel/ChannelPromise.java deleted file mode 100644 index 747a159..0000000 --- a/java/src/game/net/channel/ChannelPromise.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; -import game.net.util.concurrent.Promise; - -/** - * Special {@link ChannelFuture} which is writable. - */ -public interface ChannelPromise extends ChannelFuture, Promise { - - @Override - Channel channel(); - - @Override - ChannelPromise setSuccess(Void result); - - ChannelPromise setSuccess(); - - boolean trySuccess(); - - @Override - ChannelPromise setFailure(Throwable cause); - - @Override - ChannelPromise addListener(GenericFutureListener> listener); - - @Override - ChannelPromise addListeners(GenericFutureListener>... listeners); - - @Override - ChannelPromise removeListener(GenericFutureListener> listener); - - @Override - ChannelPromise removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelPromise sync() throws InterruptedException; - - @Override - ChannelPromise syncUninterruptibly(); - - @Override - ChannelPromise await() throws InterruptedException; - - @Override - ChannelPromise awaitUninterruptibly(); -} diff --git a/java/src/game/net/channel/CompleteChannelFuture.java b/java/src/game/net/channel/CompleteChannelFuture.java deleted file mode 100644 index eee9560..0000000 --- a/java/src/game/net/channel/CompleteChannelFuture.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.CompleteFuture; -import game.net.util.concurrent.EventExecutor; -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; - -/** - * A skeletal {@link ChannelFuture} implementation which represents a - * {@link ChannelFuture} which has been completed already. - */ -abstract class CompleteChannelFuture extends CompleteFuture implements ChannelFuture { - - private final Channel channel; - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - */ - protected CompleteChannelFuture(Channel channel, EventExecutor executor) { - super(executor); - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - } - - @Override - protected EventExecutor executor() { - EventExecutor e = super.executor(); - if (e == null) { - return channel().eventLoop(); - } else { - return e; - } - } - - @Override - public ChannelFuture addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public ChannelFuture addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public ChannelFuture removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public ChannelFuture removeListeners(GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public ChannelFuture syncUninterruptibly() { - return this; - } - - @Override - public ChannelFuture sync() throws InterruptedException { - return this; - } - - @Override - public ChannelFuture await() throws InterruptedException { - return this; - } - - @Override - public ChannelFuture awaitUninterruptibly() { - return this; - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public Void getNow() { - return null; - } -} diff --git a/java/src/game/net/channel/ConnectTimeoutException.java b/java/src/game/net/channel/ConnectTimeoutException.java deleted file mode 100644 index 5f2149b..0000000 --- a/java/src/game/net/channel/ConnectTimeoutException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.ConnectException; - -/** - * {@link ConnectException} which will be thrown if a connection could - * not be established because of a connection timeout. - */ -public class ConnectTimeoutException extends ConnectException { - private static final long serialVersionUID = 2317065249988317463L; - - public ConnectTimeoutException(String msg) { - super(msg); - } - - public ConnectTimeoutException() { - } -} diff --git a/java/src/game/net/channel/DefaultChannelConfig.java b/java/src/game/net/channel/DefaultChannelConfig.java deleted file mode 100644 index e25178c..0000000 --- a/java/src/game/net/channel/DefaultChannelConfig.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import static game.net.channel.ChannelOption.ALLOCATOR; -import static game.net.channel.ChannelOption.AUTO_CLOSE; -import static game.net.channel.ChannelOption.AUTO_READ; -import static game.net.channel.ChannelOption.CONNECT_TIMEOUT_MILLIS; -import static game.net.channel.ChannelOption.MAX_MESSAGES_PER_READ; -import static game.net.channel.ChannelOption.MESSAGE_SIZE_ESTIMATOR; -import static game.net.channel.ChannelOption.RCVBUF_ALLOCATOR; -import static game.net.channel.ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK; -import static game.net.channel.ChannelOption.WRITE_BUFFER_LOW_WATER_MARK; -import static game.net.channel.ChannelOption.WRITE_SPIN_COUNT; - -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Map.Entry; - -import game.net.buffer.ByteBufAllocator; -import game.net.channel.nio.AbstractNioByteChannel; - -/** - * The default {@link SocketChannelConfig} implementation. - */ -public class DefaultChannelConfig implements ChannelConfig { - - private static final RecvByteBufAllocator DEFAULT_RCVBUF_ALLOCATOR = AdaptiveRecvByteBufAllocator.DEFAULT; - private static final MessageSizeEstimator DEFAULT_MSG_SIZE_ESTIMATOR = DefaultMessageSizeEstimator.DEFAULT; - - private static final int DEFAULT_CONNECT_TIMEOUT = 30000; - - protected final Channel channel; - - private volatile ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; - private volatile RecvByteBufAllocator rcvBufAllocator = DEFAULT_RCVBUF_ALLOCATOR; - private volatile MessageSizeEstimator msgSizeEstimator = DEFAULT_MSG_SIZE_ESTIMATOR; - - private volatile int connectTimeoutMillis = DEFAULT_CONNECT_TIMEOUT; - private volatile int maxMessagesPerRead; - private volatile int writeSpinCount = 16; - private volatile boolean autoRead = true; - private volatile boolean autoClose = true; - private volatile int writeBufferHighWaterMark = 64 * 1024; - private volatile int writeBufferLowWaterMark = 32 * 1024; - - public DefaultChannelConfig(Channel channel) { - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - - if (channel instanceof ServerChannel || channel instanceof AbstractNioByteChannel) { - // Server channels: Accept as many incoming connections as possible. - // NIO byte channels: Implemented to reduce unnecessary system calls even if it's > 1. - // See https://github.com/netty/netty/issues/2079 - // TODO: Add some property to ChannelMetadata so we can remove the ugly instanceof - maxMessagesPerRead = 16; - } else { - maxMessagesPerRead = 1; - } - } - - @Override - - public Map, Object> getOptions() { - return getOptions( - null, - CONNECT_TIMEOUT_MILLIS, MAX_MESSAGES_PER_READ, WRITE_SPIN_COUNT, - ALLOCATOR, AUTO_READ, AUTO_CLOSE, RCVBUF_ALLOCATOR, WRITE_BUFFER_HIGH_WATER_MARK, - WRITE_BUFFER_LOW_WATER_MARK, MESSAGE_SIZE_ESTIMATOR); - } - - protected Map, Object> getOptions( - Map, Object> result, ChannelOption... options) { - if (result == null) { - result = new IdentityHashMap, Object>(); - } - for (ChannelOption o: options) { - result.put(o, getOption(o)); - } - return result; - } - - - @Override - public boolean setOptions(Map, ?> options) { - if (options == null) { - throw new NullPointerException("options"); - } - - boolean setAllOptions = true; - for (Entry, ?> e: options.entrySet()) { - if (!setOption((ChannelOption) e.getKey(), e.getValue())) { - setAllOptions = false; - } - } - - return setAllOptions; - } - - @Override - - public T getOption(ChannelOption option) { - if (option == null) { - throw new NullPointerException("option"); - } - - if (option == CONNECT_TIMEOUT_MILLIS) { - return (T) Integer.valueOf(getConnectTimeoutMillis()); - } - if (option == MAX_MESSAGES_PER_READ) { - return (T) Integer.valueOf(getMaxMessagesPerRead()); - } - if (option == WRITE_SPIN_COUNT) { - return (T) Integer.valueOf(getWriteSpinCount()); - } - if (option == ALLOCATOR) { - return (T) getAllocator(); - } - if (option == RCVBUF_ALLOCATOR) { - return (T) getRecvByteBufAllocator(); - } - if (option == AUTO_READ) { - return (T) Boolean.valueOf(isAutoRead()); - } - if (option == AUTO_CLOSE) { - return (T) Boolean.valueOf(isAutoClose()); - } - if (option == WRITE_BUFFER_HIGH_WATER_MARK) { - return (T) Integer.valueOf(getWriteBufferHighWaterMark()); - } - if (option == WRITE_BUFFER_LOW_WATER_MARK) { - return (T) Integer.valueOf(getWriteBufferLowWaterMark()); - } - if (option == MESSAGE_SIZE_ESTIMATOR) { - return (T) getMessageSizeEstimator(); - } - return null; - } - - @Override - - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == CONNECT_TIMEOUT_MILLIS) { - setConnectTimeoutMillis((Integer) value); - } else if (option == MAX_MESSAGES_PER_READ) { - setMaxMessagesPerRead((Integer) value); - } else if (option == WRITE_SPIN_COUNT) { - setWriteSpinCount((Integer) value); - } else if (option == ALLOCATOR) { - setAllocator((ByteBufAllocator) value); - } else if (option == RCVBUF_ALLOCATOR) { - setRecvByteBufAllocator((RecvByteBufAllocator) value); - } else if (option == AUTO_READ) { - setAutoRead((Boolean) value); - } else if (option == AUTO_CLOSE) { - setAutoClose((Boolean) value); - } else if (option == WRITE_BUFFER_HIGH_WATER_MARK) { - setWriteBufferHighWaterMark((Integer) value); - } else if (option == WRITE_BUFFER_LOW_WATER_MARK) { - setWriteBufferLowWaterMark((Integer) value); - } else if (option == MESSAGE_SIZE_ESTIMATOR) { - setMessageSizeEstimator((MessageSizeEstimator) value); - } else { - return false; - } - - return true; - } - - protected void validate(ChannelOption option, T value) { - if (option == null) { - throw new NullPointerException("option"); - } - option.validate(value); - } - - @Override - public int getConnectTimeoutMillis() { - return connectTimeoutMillis; - } - - @Override - public ChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - if (connectTimeoutMillis < 0) { - throw new IllegalArgumentException(String.format( - "connectTimeoutMillis: %d (expected: >= 0)", connectTimeoutMillis)); - } - this.connectTimeoutMillis = connectTimeoutMillis; - return this; - } - - @Override - public int getMaxMessagesPerRead() { - return maxMessagesPerRead; - } - - @Override - public ChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - if (maxMessagesPerRead <= 0) { - throw new IllegalArgumentException("maxMessagesPerRead: " + maxMessagesPerRead + " (expected: > 0)"); - } - this.maxMessagesPerRead = maxMessagesPerRead; - return this; - } - - @Override - public int getWriteSpinCount() { - return writeSpinCount; - } - - @Override - public ChannelConfig setWriteSpinCount(int writeSpinCount) { - if (writeSpinCount <= 0) { - throw new IllegalArgumentException( - "writeSpinCount must be a positive integer."); - } - this.writeSpinCount = writeSpinCount; - return this; - } - - @Override - public ByteBufAllocator getAllocator() { - return allocator; - } - - @Override - public ChannelConfig setAllocator(ByteBufAllocator allocator) { - if (allocator == null) { - throw new NullPointerException("allocator"); - } - this.allocator = allocator; - return this; - } - - @Override - public RecvByteBufAllocator getRecvByteBufAllocator() { - return rcvBufAllocator; - } - - @Override - public ChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - if (allocator == null) { - throw new NullPointerException("allocator"); - } - rcvBufAllocator = allocator; - return this; - } - - @Override - public boolean isAutoRead() { - return autoRead; - } - - @Override - public ChannelConfig setAutoRead(boolean autoRead) { - boolean oldAutoRead = this.autoRead; - this.autoRead = autoRead; - if (autoRead && !oldAutoRead) { - channel.read(); - } else if (!autoRead && oldAutoRead) { - autoReadCleared(); - } - return this; - } - - /** - * Is called once {@link #setAutoRead(boolean)} is called with {@code false} and {@link #isAutoRead()} was - * {@code true} before. - */ - protected void autoReadCleared() { } - - @Override - public boolean isAutoClose() { - return autoClose; - } - - @Override - public ChannelConfig setAutoClose(boolean autoClose) { - this.autoClose = autoClose; - return this; - } - - @Override - public int getWriteBufferHighWaterMark() { - return writeBufferHighWaterMark; - } - - @Override - public ChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) { - throw new IllegalArgumentException( - "writeBufferHighWaterMark cannot be less than " + - "writeBufferLowWaterMark (" + getWriteBufferLowWaterMark() + "): " + - writeBufferHighWaterMark); - } - if (writeBufferHighWaterMark < 0) { - throw new IllegalArgumentException( - "writeBufferHighWaterMark must be >= 0"); - } - this.writeBufferHighWaterMark = writeBufferHighWaterMark; - return this; - } - - @Override - public int getWriteBufferLowWaterMark() { - return writeBufferLowWaterMark; - } - - @Override - public ChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) { - throw new IllegalArgumentException( - "writeBufferLowWaterMark cannot be greater than " + - "writeBufferHighWaterMark (" + getWriteBufferHighWaterMark() + "): " + - writeBufferLowWaterMark); - } - if (writeBufferLowWaterMark < 0) { - throw new IllegalArgumentException( - "writeBufferLowWaterMark must be >= 0"); - } - this.writeBufferLowWaterMark = writeBufferLowWaterMark; - return this; - } - - @Override - public MessageSizeEstimator getMessageSizeEstimator() { - return msgSizeEstimator; - } - - @Override - public ChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - if (estimator == null) { - throw new NullPointerException("estimator"); - } - msgSizeEstimator = estimator; - return this; - } -} diff --git a/java/src/game/net/channel/DefaultChannelHandlerContext.java b/java/src/game/net/channel/DefaultChannelHandlerContext.java deleted file mode 100644 index b50a302..0000000 --- a/java/src/game/net/channel/DefaultChannelHandlerContext.java +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ -package game.net.channel; - -import game.net.util.concurrent.EventExecutorGroup; - -final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext { - - private final ChannelHandler handler; - - DefaultChannelHandlerContext( - DefaultChannelPipeline pipeline, EventExecutorGroup group, String name, ChannelHandler handler) { - super(pipeline, group, name, isInbound(handler), isOutbound(handler)); - if (handler == null) { - throw new NullPointerException("handler"); - } - this.handler = handler; - } - - @Override - public ChannelHandler handler() { - return handler; - } - - private static boolean isInbound(ChannelHandler handler) { - return handler instanceof ChannelInboundHandler; - } - - private static boolean isOutbound(ChannelHandler handler) { - return handler instanceof ChannelOutboundHandler; - } -} diff --git a/java/src/game/net/channel/DefaultChannelPipeline.java b/java/src/game/net/channel/DefaultChannelPipeline.java deleted file mode 100644 index 8b65edf..0000000 --- a/java/src/game/net/channel/DefaultChannelPipeline.java +++ /dev/null @@ -1,1067 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.WeakHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import game.net.channel.Channel.Unsafe; -import game.net.util.ReferenceCountUtil; -import game.net.util.concurrent.EventExecutor; -import game.net.util.concurrent.EventExecutorGroup; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.StringUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * The default {@link ChannelPipeline} implementation. It is usually created - * by a {@link Channel} implementation when the {@link Channel} is created. - */ -final class DefaultChannelPipeline implements ChannelPipeline { - - static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelPipeline.class); - - - private static final WeakHashMap, String>[] nameCaches = - new WeakHashMap[Runtime.getRuntime().availableProcessors()]; - - static { - for (int i = 0; i < nameCaches.length; i ++) { - nameCaches[i] = new WeakHashMap, String>(); - } - } - - final AbstractChannel channel; - - final AbstractChannelHandlerContext head; - final AbstractChannelHandlerContext tail; - - private final Map name2ctx = - new HashMap(4); - - final Map childExecutors = - new IdentityHashMap(); - - public DefaultChannelPipeline(AbstractChannel channel) { - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - - tail = new TailContext(this); - head = new HeadContext(this); - - head.next = tail; - tail.prev = head; - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelPipeline addFirst(String name, ChannelHandler handler) { - return addFirst(null, name, handler); - } - - @Override - public ChannelPipeline addFirst(EventExecutorGroup group, final String name, ChannelHandler handler) { - synchronized (this) { - checkDuplicateName(name); - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addFirst0(name, newCtx); - } - - return this; - } - - private void addFirst0(String name, AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - AbstractChannelHandlerContext nextCtx = head.next; - newCtx.prev = head; - newCtx.next = nextCtx; - head.next = newCtx; - nextCtx.prev = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addLast(String name, ChannelHandler handler) { - return addLast(null, name, handler); - } - - @Override - public ChannelPipeline addLast(EventExecutorGroup group, final String name, ChannelHandler handler) { - synchronized (this) { - checkDuplicateName(name); - - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addLast0(name, newCtx); - } - - return this; - } - - private void addLast0(final String name, AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - AbstractChannelHandlerContext prev = tail.prev; - newCtx.prev = prev; - newCtx.next = tail; - prev.next = newCtx; - tail.prev = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler) { - return addBefore(null, baseName, name, handler); - } - - @Override - public ChannelPipeline addBefore( - EventExecutorGroup group, String baseName, final String name, ChannelHandler handler) { - synchronized (this) { - AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addBefore0(name, ctx, newCtx); - } - return this; - } - - private void addBefore0( - final String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - newCtx.prev = ctx.prev; - newCtx.next = ctx; - ctx.prev.next = newCtx; - ctx.prev = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler) { - return addAfter(null, baseName, name, handler); - } - - @Override - public ChannelPipeline addAfter( - EventExecutorGroup group, String baseName, final String name, ChannelHandler handler) { - synchronized (this) { - AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - - addAfter0(name, ctx, newCtx); - } - - return this; - } - - private void addAfter0(final String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { - checkDuplicateName(name); - checkMultiplicity(newCtx); - - newCtx.prev = ctx; - newCtx.next = ctx.next; - ctx.next.prev = newCtx; - ctx.next = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addFirst(ChannelHandler... handlers) { - return addFirst(null, handlers); - } - - @Override - public ChannelPipeline addFirst(EventExecutorGroup executor, ChannelHandler... handlers) { - if (handlers == null) { - throw new NullPointerException("handlers"); - } - if (handlers.length == 0 || handlers[0] == null) { - return this; - } - - int size; - for (size = 1; size < handlers.length; size ++) { - if (handlers[size] == null) { - break; - } - } - - for (int i = size - 1; i >= 0; i --) { - ChannelHandler h = handlers[i]; - addFirst(executor, generateName(h), h); - } - - return this; - } - - @Override - public ChannelPipeline addLast(ChannelHandler... handlers) { - return addLast(null, handlers); - } - - @Override - public ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) { - if (handlers == null) { - throw new NullPointerException("handlers"); - } - - for (ChannelHandler h: handlers) { - if (h == null) { - break; - } - addLast(executor, generateName(h), h); - } - - return this; - } - - private String generateName(ChannelHandler handler) { - WeakHashMap, String> cache = nameCaches[(int) (Thread.currentThread().getId() % nameCaches.length)]; - Class handlerType = handler.getClass(); - String name; - synchronized (cache) { - name = cache.get(handlerType); - if (name == null) { - name = generateName0(handlerType); - cache.put(handlerType, name); - } - } - - synchronized (this) { - // It's not very likely for a user to put more than one handler of the same type, but make sure to avoid - // any name conflicts. Note that we don't cache the names generated here. - if (name2ctx.containsKey(name)) { - String baseName = name.substring(0, name.length() - 1); // Strip the trailing '0'. - for (int i = 1;; i ++) { - String newName = baseName + i; - if (!name2ctx.containsKey(newName)) { - name = newName; - break; - } - } - } - } - - return name; - } - - private static String generateName0(Class handlerType) { - return StringUtil.simpleClassName(handlerType) + "#0"; - } - - @Override - public ChannelPipeline remove(ChannelHandler handler) { - remove(getContextOrDie(handler)); - return this; - } - - @Override - public ChannelHandler remove(String name) { - return remove(getContextOrDie(name)).handler(); - } - - - @Override - public T remove(Class handlerType) { - return (T) remove(getContextOrDie(handlerType)).handler(); - } - - private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { - assert ctx != head && ctx != tail; - - AbstractChannelHandlerContext context; - Future future; - - synchronized (this) { - if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) { - remove0(ctx); - return ctx; - } else { - future = ctx.executor().submit(new Runnable() { - @Override - public void run() { - synchronized (DefaultChannelPipeline.this) { - remove0(ctx); - } - } - }); - context = ctx; - } - } - - // Run the following 'waiting' code outside of the above synchronized block - // in order to avoid deadlock - - waitForFuture(future); - - return context; - } - - void remove0(AbstractChannelHandlerContext ctx) { - AbstractChannelHandlerContext prev = ctx.prev; - AbstractChannelHandlerContext next = ctx.next; - prev.next = next; - next.prev = prev; - name2ctx.remove(ctx.name()); - callHandlerRemoved(ctx); - } - - @Override - public ChannelHandler removeFirst() { - if (head.next == tail) { - throw new NoSuchElementException(); - } - return remove(head.next).handler(); - } - - @Override - public ChannelHandler removeLast() { - if (head.next == tail) { - throw new NoSuchElementException(); - } - return remove(tail.prev).handler(); - } - - @Override - public ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) { - replace(getContextOrDie(oldHandler), newName, newHandler); - return this; - } - - @Override - public ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler) { - return replace(getContextOrDie(oldName), newName, newHandler); - } - - @Override - - public T replace( - Class oldHandlerType, String newName, ChannelHandler newHandler) { - return (T) replace(getContextOrDie(oldHandlerType), newName, newHandler); - } - - private ChannelHandler replace( - final AbstractChannelHandlerContext ctx, final String newName, - ChannelHandler newHandler) { - - assert ctx != head && ctx != tail; - - Future future; - synchronized (this) { - boolean sameName = ctx.name().equals(newName); - if (!sameName) { - checkDuplicateName(newName); - } - - final AbstractChannelHandlerContext newCtx = - new DefaultChannelHandlerContext(this, ctx.executor, newName, newHandler); - - if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) { - replace0(ctx, newName, newCtx); - return ctx.handler(); - } else { - future = newCtx.executor().submit(new Runnable() { - @Override - public void run() { - synchronized (DefaultChannelPipeline.this) { - replace0(ctx, newName, newCtx); - } - } - }); - } - } - - // Run the following 'waiting' code outside of the above synchronized block - // in order to avoid deadlock - - waitForFuture(future); - - return ctx.handler(); - } - - private void replace0(AbstractChannelHandlerContext oldCtx, String newName, - AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - AbstractChannelHandlerContext prev = oldCtx.prev; - AbstractChannelHandlerContext next = oldCtx.next; - newCtx.prev = prev; - newCtx.next = next; - - // Finish the replacement of oldCtx with newCtx in the linked list. - // Note that this doesn't mean events will be sent to the new handler immediately - // because we are currently at the event handler thread and no more than one handler methods can be invoked - // at the same time (we ensured that in replace().) - prev.next = newCtx; - next.prev = newCtx; - - if (!oldCtx.name().equals(newName)) { - name2ctx.remove(oldCtx.name()); - } - name2ctx.put(newName, newCtx); - - // update the reference to the replacement so forward of buffered content will work correctly - oldCtx.prev = newCtx; - oldCtx.next = newCtx; - - // Invoke newHandler.handlerAdded() first (i.e. before oldHandler.handlerRemoved() is invoked) - // because callHandlerRemoved() will trigger inboundBufferUpdated() or flush() on newHandler and those - // event handlers must be called after handlerAdded(). - callHandlerAdded(newCtx); - callHandlerRemoved(oldCtx); - } - - private static void checkMultiplicity(ChannelHandlerContext ctx) { - ChannelHandler handler = ctx.handler(); - if (handler instanceof ChannelHandlerAdapter) { - ChannelHandlerAdapter h = (ChannelHandlerAdapter) handler; - if (!h.isSharable() && h.added) { - throw new ChannelPipelineException( - h.getClass().getName() + - " is not a @Sharable handler, so can't be added or removed multiple times."); - } - h.added = true; - } - } - - private void callHandlerAdded(final ChannelHandlerContext ctx) { - if (ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) { - ctx.executor().execute(new Runnable() { - @Override - public void run() { - callHandlerAdded0(ctx); - } - }); - return; - } - callHandlerAdded0(ctx); - } - - private void callHandlerAdded0(final ChannelHandlerContext ctx) { - try { - ctx.handler().handlerAdded(ctx); - } catch (Throwable t) { - boolean removed = false; - try { - remove((AbstractChannelHandlerContext) ctx); - removed = true; - } catch (Throwable t2) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to remove a handler: " + ctx.name(), t2); - } - } - - if (removed) { - fireExceptionCaught(new ChannelPipelineException( - ctx.handler().getClass().getName() + - ".handlerAdded() has thrown an exception; removed.", t)); - } else { - fireExceptionCaught(new ChannelPipelineException( - ctx.handler().getClass().getName() + - ".handlerAdded() has thrown an exception; also failed to remove.", t)); - } - } - } - - private void callHandlerRemoved(final AbstractChannelHandlerContext ctx) { - if (ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) { - ctx.executor().execute(new Runnable() { - @Override - public void run() { - callHandlerRemoved0(ctx); - } - }); - return; - } - callHandlerRemoved0(ctx); - } - - private void callHandlerRemoved0(final AbstractChannelHandlerContext ctx) { - // Notify the complete removal. - try { - ctx.handler().handlerRemoved(ctx); - ctx.setRemoved(); - } catch (Throwable t) { - fireExceptionCaught(new ChannelPipelineException( - ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t)); - } - } - - /** - * Waits for a future to finish. If the task is interrupted, then the current thread will be interrupted. - * It is expected that the task performs any appropriate locking. - *

- * If the internal call throws a {@link Throwable}, but it is not an instance of {@link Error} or - * {@link RuntimeException}, then it is wrapped inside a {@link ChannelPipelineException} and that is - * thrown instead.

- * - * @param future wait for this future - * @see Future#get() - * @throws Error if the task threw this. - * @throws RuntimeException if the task threw this. - * @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of - * {@link Throwable}. - */ - private static void waitForFuture(Future future) { - try { - future.get(); - } catch (ExecutionException ex) { - // In the arbitrary case, we can throw Error, RuntimeException, and Exception - PlatformDependent.throwException(ex.getCause()); - } catch (InterruptedException ex) { - // Interrupt the calling thread (note that this method is not called from the event loop) - Thread.currentThread().interrupt(); - } - } - - @Override - public ChannelHandler first() { - ChannelHandlerContext first = firstContext(); - if (first == null) { - return null; - } - return first.handler(); - } - - @Override - public ChannelHandlerContext firstContext() { - AbstractChannelHandlerContext first = head.next; - if (first == tail) { - return null; - } - return head.next; - } - - @Override - public ChannelHandler last() { - AbstractChannelHandlerContext last = tail.prev; - if (last == head) { - return null; - } - return last.handler(); - } - - @Override - public ChannelHandlerContext lastContext() { - AbstractChannelHandlerContext last = tail.prev; - if (last == head) { - return null; - } - return last; - } - - @Override - public ChannelHandler get(String name) { - ChannelHandlerContext ctx = context(name); - if (ctx == null) { - return null; - } else { - return ctx.handler(); - } - } - - - @Override - public T get(Class handlerType) { - ChannelHandlerContext ctx = context(handlerType); - if (ctx == null) { - return null; - } else { - return (T) ctx.handler(); - } - } - - @Override - public ChannelHandlerContext context(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - - synchronized (this) { - return name2ctx.get(name); - } - } - - @Override - public ChannelHandlerContext context(ChannelHandler handler) { - if (handler == null) { - throw new NullPointerException("handler"); - } - - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - - if (ctx == null) { - return null; - } - - if (ctx.handler() == handler) { - return ctx; - } - - ctx = ctx.next; - } - } - - @Override - public ChannelHandlerContext context(Class handlerType) { - if (handlerType == null) { - throw new NullPointerException("handlerType"); - } - - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == null) { - return null; - } - if (handlerType.isAssignableFrom(ctx.handler().getClass())) { - return ctx; - } - ctx = ctx.next; - } - } - - @Override - public List names() { - List list = new ArrayList(); - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == null) { - return list; - } - list.add(ctx.name()); - ctx = ctx.next; - } - } - - @Override - public Map toMap() { - Map map = new LinkedHashMap(); - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == tail) { - return map; - } - map.put(ctx.name(), ctx.handler()); - ctx = ctx.next; - } - } - - @Override - public Iterator> iterator() { - return toMap().entrySet().iterator(); - } - - /** - * Returns the {@link String} representation of this pipeline. - */ - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append(StringUtil.simpleClassName(this)); - buf.append('{'); - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == tail) { - break; - } - - buf.append('('); - buf.append(ctx.name()); - buf.append(" = "); - buf.append(ctx.handler().getClass().getName()); - buf.append(')'); - - ctx = ctx.next; - if (ctx == tail) { - break; - } - - buf.append(", "); - } - buf.append('}'); - return buf.toString(); - } - - @Override - public ChannelPipeline fireChannelRegistered() { - head.fireChannelRegistered(); - return this; - } - - @Override - public ChannelPipeline fireChannelUnregistered() { - head.fireChannelUnregistered(); - - // Remove all handlers sequentially if channel is closed and unregistered. - if (!channel.isOpen()) { - teardownAll(); - } - return this; - } - - /** - * Removes all handlers from the pipeline one by one from tail (exclusive) to head (inclusive) to trigger - * handlerRemoved(). Note that the tail handler is excluded because it's neither an outbound handler nor it - * does anything in handlerRemoved(). - */ - private void teardownAll() { - tail.prev.teardown(); - } - - @Override - public ChannelPipeline fireChannelActive() { - head.fireChannelActive(); - - if (channel.config().isAutoRead()) { - channel.read(); - } - - return this; - } - - @Override - public ChannelPipeline fireChannelInactive() { - head.fireChannelInactive(); - return this; - } - - @Override - public ChannelPipeline fireExceptionCaught(Throwable cause) { - head.fireExceptionCaught(cause); - return this; - } - - @Override - public ChannelPipeline fireUserEventTriggered(Object event) { - head.fireUserEventTriggered(event); - return this; - } - - @Override - public ChannelPipeline fireChannelRead(Object msg) { - head.fireChannelRead(msg); - return this; - } - - @Override - public ChannelPipeline fireChannelReadComplete() { - head.fireChannelReadComplete(); - if (channel.config().isAutoRead()) { - read(); - } - return this; - } - - @Override - public ChannelPipeline fireChannelWritabilityChanged() { - head.fireChannelWritabilityChanged(); - return this; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress) { - return tail.bind(localAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress) { - return tail.connect(remoteAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - return tail.connect(remoteAddress, localAddress); - } - - @Override - public ChannelFuture disconnect() { - return tail.disconnect(); - } - - @Override - public ChannelFuture close() { - return tail.close(); - } - - @Override - public ChannelFuture deregister() { - return tail.deregister(); - } - - @Override - public ChannelPipeline flush() { - tail.flush(); - return this; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { - return tail.bind(localAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { - return tail.connect(remoteAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - return tail.connect(remoteAddress, localAddress, promise); - } - - @Override - public ChannelFuture disconnect(ChannelPromise promise) { - return tail.disconnect(promise); - } - - @Override - public ChannelFuture close(ChannelPromise promise) { - return tail.close(promise); - } - - @Override - public ChannelFuture deregister(final ChannelPromise promise) { - return tail.deregister(promise); - } - - @Override - public ChannelPipeline read() { - tail.read(); - return this; - } - - @Override - public ChannelFuture write(Object msg) { - return tail.write(msg); - } - - @Override - public ChannelFuture write(Object msg, ChannelPromise promise) { - return tail.write(msg, promise); - } - - @Override - public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { - return tail.writeAndFlush(msg, promise); - } - - @Override - public ChannelFuture writeAndFlush(Object msg) { - return tail.writeAndFlush(msg); - } - - private void checkDuplicateName(String name) { - if (name2ctx.containsKey(name)) { - throw new IllegalArgumentException("Duplicate handler name: " + name); - } - } - - private AbstractChannelHandlerContext getContextOrDie(String name) { - AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(name); - if (ctx == null) { - throw new NoSuchElementException(name); - } else { - return ctx; - } - } - - private AbstractChannelHandlerContext getContextOrDie(ChannelHandler handler) { - AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handler); - if (ctx == null) { - throw new NoSuchElementException(handler.getClass().getName()); - } else { - return ctx; - } - } - - private AbstractChannelHandlerContext getContextOrDie(Class handlerType) { - AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handlerType); - if (ctx == null) { - throw new NoSuchElementException(handlerType.getName()); - } else { - return ctx; - } - } - - // A special catch-all handler that handles both bytes and messages. - static final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler { - - private static final String TAIL_NAME = generateName0(TailContext.class); - - TailContext(DefaultChannelPipeline pipeline) { - super(pipeline, null, TAIL_NAME, true, false); - } - - @Override - public ChannelHandler handler() { - return this; - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.warn( - "An exceptionCaught() event was fired, and it reached at the tail of the pipeline. " + - "It usually means the last handler in the pipeline did not handle the exception.", cause); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - try { - logger.debug( - "Discarded inbound message {} that reached at the tail of the pipeline. " + - "Please check your pipeline configuration.", msg); - } finally { - ReferenceCountUtil.release(msg); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { } - } - - static final class HeadContext extends AbstractChannelHandlerContext implements ChannelOutboundHandler { - - private static final String HEAD_NAME = generateName0(HeadContext.class); - - protected final Unsafe unsafe; - - HeadContext(DefaultChannelPipeline pipeline) { - super(pipeline, null, HEAD_NAME, false, true); - unsafe = pipeline.channel().unsafe(); - } - - @Override - public ChannelHandler handler() { - return this; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - @Override - public void bind( - ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) - throws Exception { - unsafe.bind(localAddress, promise); - } - - @Override - public void connect( - ChannelHandlerContext ctx, - SocketAddress remoteAddress, SocketAddress localAddress, - ChannelPromise promise) throws Exception { - unsafe.connect(remoteAddress, localAddress, promise); - } - - @Override - public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - unsafe.disconnect(promise); - } - - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - unsafe.close(promise); - } - - @Override - public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - unsafe.deregister(promise); - } - - @Override - public void read(ChannelHandlerContext ctx) { - unsafe.beginRead(); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - unsafe.write(msg, promise); - } - - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - unsafe.flush(); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ctx.fireExceptionCaught(cause); - } - } -} diff --git a/java/src/game/net/channel/DefaultChannelPromise.java b/java/src/game/net/channel/DefaultChannelPromise.java deleted file mode 100644 index 488f847..0000000 --- a/java/src/game/net/channel/DefaultChannelPromise.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.DefaultPromise; -import game.net.util.concurrent.EventExecutor; -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; - -/** - * The default {@link ChannelPromise} implementation. It is recommended to use {@link Channel#newPromise()} to create - * a new {@link ChannelPromise} rather than calling the constructor explicitly. - */ -public class DefaultChannelPromise extends DefaultPromise implements ChannelPromise { - - private final Channel channel; -// private long checkpoint; - - /** - * Creates a new instance. - * - * @param channel - * the {@link Channel} associated with this future - */ - public DefaultChannelPromise(Channel channel) { - this.channel = channel; - } - - /** - * Creates a new instance. - * - * @param channel - * the {@link Channel} associated with this future - */ - public DefaultChannelPromise(Channel channel, EventExecutor executor) { - super(executor); - this.channel = channel; - } - - @Override - protected EventExecutor executor() { - EventExecutor e = super.executor(); - if (e == null) { - return channel().eventLoop(); - } else { - return e; - } - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelPromise setSuccess() { - return setSuccess(null); - } - - @Override - public ChannelPromise setSuccess(Void result) { - super.setSuccess(result); - return this; - } - - @Override - public boolean trySuccess() { - return trySuccess(null); - } - - @Override - public ChannelPromise setFailure(Throwable cause) { - super.setFailure(cause); - return this; - } - - @Override - public ChannelPromise addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public ChannelPromise addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public ChannelPromise removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public ChannelPromise removeListeners(GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public ChannelPromise sync() throws InterruptedException { - super.sync(); - return this; - } - - @Override - public ChannelPromise syncUninterruptibly() { - super.syncUninterruptibly(); - return this; - } - - @Override - public ChannelPromise await() throws InterruptedException { - super.await(); - return this; - } - - @Override - public ChannelPromise awaitUninterruptibly() { - super.awaitUninterruptibly(); - return this; - } - -// @Override -// public long flushCheckpoint() { -// return checkpoint; -// } - -// @Override -// public void flushCheckpoint(long checkpoint) { -// this.checkpoint = checkpoint; -// } - -// @Override -// public ChannelPromise promise() { -// return this; -// } - - @Override - protected void checkDeadLock() { - if (channel().isRegistered()) { - super.checkDeadLock(); - } - } -} diff --git a/java/src/game/net/channel/DefaultMessageSizeEstimator.java b/java/src/game/net/channel/DefaultMessageSizeEstimator.java deleted file mode 100644 index ab23172..0000000 --- a/java/src/game/net/channel/DefaultMessageSizeEstimator.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.buffer.ByteBuf; - -/** - * Default {@link MessageSizeEstimator} implementation which supports the estimation of the size of - * {@link ByteBuf}, {@link ByteBufHolder} and {@link FileRegion}. - */ -public final class DefaultMessageSizeEstimator implements MessageSizeEstimator { - - private static final class HandleImpl implements Handle { - private final int unknownSize; - - private HandleImpl(int unknownSize) { - this.unknownSize = unknownSize; - } - - @Override - public int size(Object msg) { - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).readableBytes(); - } -// if (msg instanceof ByteBufHolder) { -// return ((ByteBufHolder) msg).content().readableBytes(); -// } -// if (msg instanceof FileRegion) { -// return 0; -// } - return unknownSize; - } - } - - /** - * Return the default implementation which returns {@code -1} for unknown messages. - */ - public static final MessageSizeEstimator DEFAULT = new DefaultMessageSizeEstimator(0); - - private final Handle handle; - - /** - * Create a new instance - * - * @param unknownSize The size which is returned for unknown messages. - */ - public DefaultMessageSizeEstimator(int unknownSize) { - if (unknownSize < 0) { - throw new IllegalArgumentException("unknownSize: " + unknownSize + " (expected: >= 0)"); - } - handle = new HandleImpl(unknownSize); - } - - @Override - public Handle newHandle() { - return handle; - } -} diff --git a/java/src/game/net/channel/EventLoop.java b/java/src/game/net/channel/EventLoop.java deleted file mode 100644 index 3dd2a8f..0000000 --- a/java/src/game/net/channel/EventLoop.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.EventExecutor; - -/** - * Will handle all the I/O-Operations for a {@link Channel} once it was registered. - * - * One {@link EventLoop} instance will usually handle more then one {@link Channel} but this may depend on - * implementation details and internals. - * - */ -public interface EventLoop extends EventExecutor, EventLoopGroup { - @Override - EventLoopGroup parent(); -} diff --git a/java/src/game/net/channel/EventLoopException.java b/java/src/game/net/channel/EventLoopException.java deleted file mode 100644 index 62dc98c..0000000 --- a/java/src/game/net/channel/EventLoopException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * Special {@link ChannelException} which will be thrown by {@link EventLoop} and {@link EventLoopGroup} - * implementations when an error occurs. - */ -public class EventLoopException extends ChannelException { - - private static final long serialVersionUID = -8969100344583703616L; - - public EventLoopException() { - } - - public EventLoopException(String message, Throwable cause) { - super(message, cause); - } - - public EventLoopException(String message) { - super(message); - } - - public EventLoopException(Throwable cause) { - super(cause); - } - -} diff --git a/java/src/game/net/channel/EventLoopGroup.java b/java/src/game/net/channel/EventLoopGroup.java deleted file mode 100644 index bb32628..0000000 --- a/java/src/game/net/channel/EventLoopGroup.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.EventExecutorGroup; - -/** - * Special {@link EventExecutorGroup} which allows to register {@link Channel}'s that get - * processed for later selection during the event loop. - * - */ -public interface EventLoopGroup extends EventExecutorGroup { - /** - * Return the next {@link EventLoop} to use - */ - @Override - EventLoop next(); - - /** - * Register a {@link Channel} with this {@link EventLoop}. The returned {@link ChannelFuture} - * will get notified once the registration was complete. - */ - ChannelFuture register(Channel channel); - - /** - * Register a {@link Channel} with this {@link EventLoop}. The passed {@link ChannelFuture} - * will get notified once the registration was complete and also will get returned. - */ - ChannelFuture register(Channel channel, ChannelPromise promise); -} diff --git a/java/src/game/net/channel/FailedChannelFuture.java b/java/src/game/net/channel/FailedChannelFuture.java deleted file mode 100644 index 48a4a06..0000000 --- a/java/src/game/net/channel/FailedChannelFuture.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.EventExecutor; -import game.net.util.internal.PlatformDependent; - -/** - * The {@link CompleteChannelFuture} which is failed already. It is - * recommended to use {@link Channel#newFailedFuture(Throwable)} - * instead of calling the constructor of this future. - */ -final class FailedChannelFuture extends CompleteChannelFuture { - - private final Throwable cause; - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - * @param cause the cause of failure - */ - FailedChannelFuture(Channel channel, EventExecutor executor, Throwable cause) { - super(channel, executor); - if (cause == null) { - throw new NullPointerException("cause"); - } - this.cause = cause; - } - - @Override - public Throwable cause() { - return cause; - } - - @Override - public boolean isSuccess() { - return false; - } - - @Override - public ChannelFuture sync() { - PlatformDependent.throwException(cause); - return this; - } - - @Override - public ChannelFuture syncUninterruptibly() { - PlatformDependent.throwException(cause); - return this; - } -} diff --git a/java/src/game/net/channel/MessageSizeEstimator.java b/java/src/game/net/channel/MessageSizeEstimator.java deleted file mode 100644 index 854adab..0000000 --- a/java/src/game/net/channel/MessageSizeEstimator.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * Responsible to estimate size of a message. The size represent how much memory the message will ca. reserve in - * memory. - */ -public interface MessageSizeEstimator { - - /** - * Creates a new handle. The handle provides the actual operations. - */ - Handle newHandle(); - - interface Handle { - - /** - * Calculate the size of the given message. - * - * @param msg The message for which the size should be calculated - * @return size The size in bytes. The returned size must be >= 0 - */ - int size(Object msg); - } -} diff --git a/java/src/game/net/channel/MultithreadEventLoopGroup.java b/java/src/game/net/channel/MultithreadEventLoopGroup.java deleted file mode 100644 index 2b3631c..0000000 --- a/java/src/game/net/channel/MultithreadEventLoopGroup.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.util.concurrent.ThreadFactory; - -import game.net.util.concurrent.DefaultThreadFactory; -import game.net.util.concurrent.MultithreadEventExecutorGroup; -import game.net.util.internal.SystemPropertyUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Abstract base class for {@link EventLoopGroup} implementations that handles their tasks with multiple threads at - * the same time. - */ -public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(MultithreadEventLoopGroup.class); - - private static final int DEFAULT_EVENT_LOOP_THREADS; - - static { - DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt( - "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2)); - - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS); - } - } - - /** - * @see {@link MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, ThreadFactory, Object...)} - */ - protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) { - super(nThreads == 0? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args); - } - - @Override - protected ThreadFactory newDefaultThreadFactory() { - return new DefaultThreadFactory(getClass(), Thread.MAX_PRIORITY); - } - - @Override - public EventLoop next() { - return (EventLoop) super.next(); - } - - @Override - public ChannelFuture register(Channel channel) { - return next().register(channel); - } - - @Override - public ChannelFuture register(Channel channel, ChannelPromise promise) { - return next().register(channel, promise); - } -} diff --git a/java/src/game/net/channel/RecvByteBufAllocator.java b/java/src/game/net/channel/RecvByteBufAllocator.java deleted file mode 100644 index 99142f0..0000000 --- a/java/src/game/net/channel/RecvByteBufAllocator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.buffer.ByteBuf; -import game.net.buffer.ByteBufAllocator; - -/** - * Allocates a new receive buffer whose capacity is probably large enough to read all inbound data and small enough - * not to waste its space. - */ -public interface RecvByteBufAllocator { - - /** - * Creates a new handle. The handle provides the actual operations and keeps the internal information which is - * required for predicting an optimal buffer capacity. - */ - Handle newHandle(); - - interface Handle { - /** - * Creates a new receive buffer whose capacity is probably large enough to read all inbound data and small - * enough not to waste its space. - */ - ByteBuf allocate(ByteBufAllocator alloc); - - /** - * Similar to {@link #allocate(ByteBufAllocator)} except that it does not allocate anything but just tells the - * capacity. - */ - int guess(); - - /** - * Records the the actual number of read bytes in the previous read operation so that the allocator allocates - * the buffer with potentially more correct capacity. - * - * @param actualReadBytes the actual number of read bytes in the previous read operation - */ - void record(int actualReadBytes); - } -} diff --git a/java/src/game/net/channel/ServerChannel.java b/java/src/game/net/channel/ServerChannel.java deleted file mode 100644 index b636192..0000000 --- a/java/src/game/net/channel/ServerChannel.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -/** - * A {@link Channel} that accepts an incoming connection attempt and creates - * its child {@link Channel}s by accepting them. {@link ServerSocketChannel} is - * a good example. - */ -public interface ServerChannel extends Channel { - // This is a tag interface. -} diff --git a/java/src/game/net/channel/SimpleChannelInboundHandler.java b/java/src/game/net/channel/SimpleChannelInboundHandler.java deleted file mode 100644 index 3a6bed1..0000000 --- a/java/src/game/net/channel/SimpleChannelInboundHandler.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.ReferenceCountUtil; -import game.net.util.internal.TypeParameterMatcher; - -/** - * {@link ChannelInboundHandlerAdapter} which allows to explicit only handle a specific type of messages. - * - * For example here is an implementation which only handle {@link String} messages. - * - *
- *     public class StringHandler extends
- *             {@link SimpleChannelInboundHandler}<{@link String}> {
- *
- *         {@code @Override}
- *         protected void channelRead0({@link ChannelHandlerContext} ctx, {@link String} message)
- *                 throws {@link Exception} {
- *             System.out.println(message);
- *         }
- *     }
- * 
- * - * Be aware that depending of the constructor parameters it will release all handled messages by pass them to - * {@link ReferenceCountUtil#release(Object)}. In this case you may need to use - * {@link ReferenceCountUtil#retain(Object)} if you pass the object to the next handler in the {@link ChannelPipeline}. - * - *

Forward compatibility notice

- *

- * Please keep in mind that {@link #channelRead0(ChannelHandlerContext, I)} will be renamed to - * {@code messageReceived(ChannelHandlerContext, I)} in 5.0. - *

- */ -public abstract class SimpleChannelInboundHandler extends ChannelInboundHandlerAdapter { - - private final TypeParameterMatcher matcher; - private final boolean autoRelease; - - /** - * @see {@link #SimpleChannelInboundHandler(boolean)} with {@code true} as boolean parameter. - */ - protected SimpleChannelInboundHandler() { - this(true); - } - - /** - * Create a new instance which will try to detect the types to match out of the type parameter of the class. - * - * @param autoRelease {@code true} if handled messages should be released automatically by pass them to - * {@link ReferenceCountUtil#release(Object)}. - */ - protected SimpleChannelInboundHandler(boolean autoRelease) { - matcher = TypeParameterMatcher.find(this, SimpleChannelInboundHandler.class, "I"); - this.autoRelease = autoRelease; - } - - /** - * @see {@link #SimpleChannelInboundHandler(Class, boolean)} with {@code true} as boolean value. - */ - protected SimpleChannelInboundHandler(Class inboundMessageType) { - this(inboundMessageType, true); - } - - /** - * Create a new instance - * - * @param inboundMessageType The type of messages to match - * @param autoRelease {@code true} if handled messages should be released automatically by pass them to - * {@link ReferenceCountUtil#release(Object)}. - */ - protected SimpleChannelInboundHandler(Class inboundMessageType, boolean autoRelease) { - matcher = TypeParameterMatcher.get(inboundMessageType); - this.autoRelease = autoRelease; - } - - /** - * Returns {@code true} if the given message should be handled. If {@code false} it will be passed to the next - * {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - public boolean acceptInboundMessage(Object msg) throws Exception { - return matcher.match(msg); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - boolean release = true; - try { - if (acceptInboundMessage(msg)) { - - I imsg = (I) msg; - channelRead0(ctx, imsg); - } else { - release = false; - ctx.fireChannelRead(msg); - } - } finally { - if (autoRelease && release) { - ReferenceCountUtil.release(msg); - } - } - } - - /** - * Please keep in mind that this method will be renamed to - * {@code messageReceived(ChannelHandlerContext, I)} in 5.0. - * - * Is called for each message of type {@link I}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler} - * belongs to - * @param msg the message to handle - * @throws Exception is thrown if an error occurred - */ - protected abstract void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception; -} diff --git a/java/src/game/net/channel/SingleThreadEventLoop.java b/java/src/game/net/channel/SingleThreadEventLoop.java deleted file mode 100644 index 72b16c4..0000000 --- a/java/src/game/net/channel/SingleThreadEventLoop.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.util.concurrent.ThreadFactory; - -import game.net.util.concurrent.SingleThreadEventExecutor; - -/** - * Abstract base class for {@link EventLoop}'s that execute all its submitted tasks in a single thread. - * - */ -public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop { - - /** - * @see {@link SingleThreadEventExecutor#SingleThreadEventExecutor(EventExecutorGroup, ThreadFactory, boolean)} - */ - protected SingleThreadEventLoop(EventLoopGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) { - super(parent, threadFactory, addTaskWakesUp); - } - - @Override - public EventLoopGroup parent() { - return (EventLoopGroup) super.parent(); - } - - @Override - public EventLoop next() { - return (EventLoop) super.next(); - } - - @Override - public ChannelFuture register(Channel channel) { - return register(channel, new DefaultChannelPromise(channel, this)); - } - - @Override - public ChannelFuture register(final Channel channel, final ChannelPromise promise) { - if (channel == null) { - throw new NullPointerException("channel"); - } - if (promise == null) { - throw new NullPointerException("promise"); - } - - channel.unsafe().register(this, promise); - return promise; - } - - @Override - protected boolean wakesUpForTask(Runnable task) { - return !(task instanceof NonWakeupRunnable); - } - - /** - * Marker interface for {@linkRunnable} that will not trigger an {@link #wakeup(boolean)} in all cases. - */ - interface NonWakeupRunnable extends Runnable { } -} diff --git a/java/src/game/net/channel/SucceededChannelFuture.java b/java/src/game/net/channel/SucceededChannelFuture.java deleted file mode 100644 index b11dda4..0000000 --- a/java/src/game/net/channel/SucceededChannelFuture.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import game.net.util.concurrent.EventExecutor; - -/** - * The {@link CompleteChannelFuture} which is succeeded already. It is - * recommended to use {@link Channel#newSucceededFuture()} instead of - * calling the constructor of this future. - */ -final class SucceededChannelFuture extends CompleteChannelFuture { - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - */ - SucceededChannelFuture(Channel channel, EventExecutor executor) { - super(channel, executor); - } - - @Override - public Throwable cause() { - return null; - } - - @Override - public boolean isSuccess() { - return true; - } -} diff --git a/java/src/game/net/channel/VoidChannelPromise.java b/java/src/game/net/channel/VoidChannelPromise.java deleted file mode 100644 index 2a7f811..0000000 --- a/java/src/game/net/channel/VoidChannelPromise.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel; - -import java.util.concurrent.TimeUnit; - -import game.net.util.concurrent.AbstractFuture; -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; - -final class VoidChannelPromise extends AbstractFuture implements ChannelPromise { - - private final Channel channel; - private final boolean fireException; - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - */ - VoidChannelPromise(Channel channel, boolean fireException) { - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - this.fireException = fireException; - } - - @Override - public VoidChannelPromise addListener(GenericFutureListener> listener) { - fail(); - return this; - } - - @Override - public VoidChannelPromise addListeners(GenericFutureListener>... listeners) { - fail(); - return this; - } - - @Override - public VoidChannelPromise removeListener(GenericFutureListener> listener) { - // NOOP - return this; - } - - @Override - public VoidChannelPromise removeListeners(GenericFutureListener>... listeners) { - // NOOP - return this; - } - - @Override - public VoidChannelPromise await() throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return this; - } - - @Override - public boolean await(long timeout, TimeUnit unit) { - fail(); - return false; - } - - @Override - public boolean await(long timeoutMillis) { - fail(); - return false; - } - - @Override - public VoidChannelPromise awaitUninterruptibly() { - fail(); - return this; - } - - @Override - public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - fail(); - return false; - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - fail(); - return false; - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public boolean isDone() { - return false; - } - - @Override - public boolean isSuccess() { - return false; - } - - @Override - public boolean setUncancellable() { - return true; - } - - @Override - public boolean isCancellable() { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public Throwable cause() { - return null; - } - - @Override - public VoidChannelPromise sync() { - fail(); - return this; - } - - @Override - public VoidChannelPromise syncUninterruptibly() { - fail(); - return this; - } - @Override - public VoidChannelPromise setFailure(Throwable cause) { - fireException(cause); - return this; - } - - @Override - public VoidChannelPromise setSuccess() { - return this; - } - - @Override - public boolean tryFailure(Throwable cause) { - fireException(cause); - return false; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean trySuccess() { - return false; - } - - private static void fail() { - throw new IllegalStateException("void future"); - } - - @Override - public VoidChannelPromise setSuccess(Void result) { - return this; - } - - @Override - public boolean trySuccess(Void result) { - return false; - } - - @Override - public Void getNow() { - return null; - } - - private void fireException(Throwable cause) { - // Only fire the exception if the channel is open and registered - // if not the pipeline is not setup and so it would hit the tail - // of the pipeline. - // See https://github.com/netty/netty/issues/1517 - if (fireException && channel.isRegistered()) { - channel.pipeline().fireExceptionCaught(cause); - } - } -} diff --git a/java/src/game/net/channel/local/LocalAddress.java b/java/src/game/net/channel/local/LocalAddress.java deleted file mode 100644 index 446b802..0000000 --- a/java/src/game/net/channel/local/LocalAddress.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.local; - -import java.net.SocketAddress; - -import game.net.channel.Channel; - -/** - * An endpoint in the local transport. Each endpoint is identified by a unique - * case-insensitive string. - */ -public final class LocalAddress extends SocketAddress implements Comparable { - - private static final long serialVersionUID = 4644331421130916435L; - - public static final LocalAddress ANY = new LocalAddress("ANY"); - - private final String id; - private final String strVal; - - /** - * Creates a new ephemeral port based on the ID of the specified channel. - * Note that we prepend an upper-case character so that it never conflicts with - * the addresses created by a user, which are always lower-cased on construction time. - */ - LocalAddress(Channel channel) { - StringBuilder buf = new StringBuilder(16); - buf.append("local:E"); - buf.append(Long.toHexString(channel.hashCode() & 0xFFFFFFFFL | 0x100000000L)); - buf.setCharAt(7, ':'); - id = buf.substring(6); - strVal = buf.toString(); - } - - /** - * Creates a new instance with the specified ID. - */ - public LocalAddress(String id) { - if (id == null) { - throw new NullPointerException("id"); - } - id = id.trim().toLowerCase(); - if (id.isEmpty()) { - throw new IllegalArgumentException("empty id"); - } - this.id = id; - strVal = "local:" + id; - } - - /** - * Returns the ID of this address. - */ - public String id() { - return id; - } - - @Override - public int hashCode() { - return id.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof LocalAddress)) { - return false; - } - - return id.equals(((LocalAddress) o).id); - } - - @Override - public int compareTo(LocalAddress o) { - return id.compareTo(o.id); - } - - @Override - public String toString() { - return strVal; - } -} diff --git a/java/src/game/net/channel/local/LocalChannel.java b/java/src/game/net/channel/local/LocalChannel.java deleted file mode 100644 index 54ddb0d..0000000 --- a/java/src/game/net/channel/local/LocalChannel.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.local; - -import java.net.SocketAddress; -import java.nio.channels.AlreadyConnectedException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.ConnectionPendingException; -import java.nio.channels.NotYetConnectedException; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.Queue; - -import game.net.channel.AbstractChannel; -import game.net.channel.Channel; -import game.net.channel.ChannelConfig; -import game.net.channel.ChannelException; -import game.net.channel.ChannelMetadata; -import game.net.channel.ChannelOutboundBuffer; -import game.net.channel.ChannelPipeline; -import game.net.channel.ChannelPromise; -import game.net.channel.DefaultChannelConfig; -import game.net.channel.EventLoop; -import game.net.channel.SingleThreadEventLoop; -import game.net.util.ReferenceCountUtil; -import game.net.util.concurrent.SingleThreadEventExecutor; -import game.net.util.internal.InternalThreadLocalMap; - -/** - * A {@link Channel} for the local transport. - */ -public class LocalChannel extends AbstractChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - - private static final int MAX_READER_STACK_DEPTH = 8; - - private final ChannelConfig config = new DefaultChannelConfig(this); - private final Queue inboundBuffer = new ArrayDeque(); - private final Runnable readTask = new Runnable() { - @Override - public void run() { - ChannelPipeline pipeline = pipeline(); - for (;;) { - Object m = inboundBuffer.poll(); - if (m == null) { - break; - } - pipeline.fireChannelRead(m); - } - pipeline.fireChannelReadComplete(); - } - }; - - private final Runnable shutdownHook = new Runnable() { - @Override - public void run() { - unsafe().close(unsafe().voidPromise()); - } - }; - - private volatile int state; // 0 - open, 1 - bound, 2 - connected, 3 - closed - private volatile LocalChannel peer; - private volatile LocalAddress localAddress; - private volatile LocalAddress remoteAddress; - private volatile ChannelPromise connectPromise; - private volatile boolean readInProgress; - private volatile boolean registerInProgress; - - public LocalChannel() { - super(null); - } - - LocalChannel(LocalServerChannel parent, LocalChannel peer) { - super(parent); - this.peer = peer; - localAddress = parent.localAddress(); - remoteAddress = peer.localAddress(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public ChannelConfig config() { - return config; - } - - @Override - public LocalServerChannel parent() { - return (LocalServerChannel) super.parent(); - } - - @Override - public LocalAddress localAddress() { - return (LocalAddress) super.localAddress(); - } - - @Override - public LocalAddress remoteAddress() { - return (LocalAddress) super.remoteAddress(); - } - - @Override - public boolean isOpen() { - return state < 3; - } - - @Override - public boolean isActive() { - return state == 2; - } - - @Override - protected AbstractUnsafe newUnsafe() { - return new LocalUnsafe(); - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof SingleThreadEventLoop; - } - - @Override - protected SocketAddress localAddress0() { - return localAddress; - } - - @Override - protected SocketAddress remoteAddress0() { - return remoteAddress; - } - - @Override - protected void doRegister() throws Exception { - // Check if both peer and parent are non-null because this channel was created by a LocalServerChannel. - // This is needed as a peer may not be null also if a LocalChannel was connected before and - // deregistered / registered later again. - // - // See https://github.com/netty/netty/issues/2400 - if (peer != null && parent() != null) { - // Store the peer in a local variable as it may be set to null if doClose() is called. - // Because of this we also set registerInProgress to true as we check for this in doClose() and make sure - // we delay the fireChannelInactive() to be fired after the fireChannelActive() and so keep the correct - // order of events. - // - // See https://github.com/netty/netty/issues/2144 - final LocalChannel peer = this.peer; - registerInProgress = true; - state = 2; - - peer.remoteAddress = parent().localAddress(); - peer.state = 2; - - // Always call peer.eventLoop().execute() even if peer.eventLoop().inEventLoop() is true. - // This ensures that if both channels are on the same event loop, the peer's channelActive - // event is triggered *after* this channel's channelRegistered event, so that this channel's - // pipeline is fully initialized by ChannelInitializer before any channelRead events. - peer.eventLoop().execute(new Runnable() { - @Override - public void run() { - registerInProgress = false; - peer.pipeline().fireChannelActive(); - peer.connectPromise.setSuccess(); - } - }); - } - ((SingleThreadEventExecutor) eventLoop()).addShutdownHook(shutdownHook); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - this.localAddress = - LocalChannelRegistry.register(this, this.localAddress, - localAddress); - state = 1; - } - - @Override - protected void doDisconnect() throws Exception { - doClose(); - } - - @Override - protected void doClose() throws Exception { - if (state <= 2) { - // Update all internal state before the closeFuture is notified. - if (localAddress != null) { - if (parent() == null) { - LocalChannelRegistry.unregister(localAddress); - } - localAddress = null; - } - state = 3; - } - - final LocalChannel peer = this.peer; - if (peer != null && peer.isActive()) { - // Need to execute the close in the correct EventLoop - // See https://github.com/netty/netty/issues/1777 - EventLoop eventLoop = peer.eventLoop(); - - // Also check if the registration was not done yet. In this case we submit the close to the EventLoop - // to make sure it is run after the registration completes. - // - // See https://github.com/netty/netty/issues/2144 - if (eventLoop.inEventLoop() && !registerInProgress) { - peer.unsafe().close(unsafe().voidPromise()); - } else { - peer.eventLoop().execute(new Runnable() { - @Override - public void run() { - peer.unsafe().close(unsafe().voidPromise()); - } - }); - } - this.peer = null; - } - } - - @Override - protected void doDeregister() throws Exception { - // Just remove the shutdownHook as this Channel may be closed later or registered to another EventLoop - ((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook); - } - - @Override - protected void doBeginRead() throws Exception { - if (readInProgress) { - return; - } - - ChannelPipeline pipeline = pipeline(); - Queue inboundBuffer = this.inboundBuffer; - if (inboundBuffer.isEmpty()) { - readInProgress = true; - return; - } - - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final Integer stackDepth = threadLocals.localChannelReaderStackDepth(); - if (stackDepth < MAX_READER_STACK_DEPTH) { - threadLocals.setLocalChannelReaderStackDepth(stackDepth + 1); - try { - for (;;) { - Object received = inboundBuffer.poll(); - if (received == null) { - break; - } - pipeline.fireChannelRead(received); - } - pipeline.fireChannelReadComplete(); - } finally { - threadLocals.setLocalChannelReaderStackDepth(stackDepth); - } - } else { - eventLoop().execute(readTask); - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - if (state < 2) { - throw new NotYetConnectedException(); - } - if (state > 2) { - throw new ClosedChannelException(); - } - - final LocalChannel peer = this.peer; - final ChannelPipeline peerPipeline = peer.pipeline(); - final EventLoop peerLoop = peer.eventLoop(); - - if (peerLoop == eventLoop()) { - for (;;) { - Object msg = in.current(); - if (msg == null) { - break; - } - peer.inboundBuffer.add(msg); - ReferenceCountUtil.retain(msg); - in.remove(); - } - finishPeerRead(peer, peerPipeline); - } else { - // Use a copy because the original msgs will be recycled by AbstractChannel. - final Object[] msgsCopy = new Object[in.size()]; - for (int i = 0; i < msgsCopy.length; i ++) { - msgsCopy[i] = ReferenceCountUtil.retain(in.current()); - in.remove(); - } - - peerLoop.execute(new Runnable() { - @Override - public void run() { - Collections.addAll(peer.inboundBuffer, msgsCopy); - finishPeerRead(peer, peerPipeline); - } - }); - } - } - - private static void finishPeerRead(LocalChannel peer, ChannelPipeline peerPipeline) { - if (peer.readInProgress) { - peer.readInProgress = false; - for (;;) { - Object received = peer.inboundBuffer.poll(); - if (received == null) { - break; - } - peerPipeline.fireChannelRead(received); - } - peerPipeline.fireChannelReadComplete(); - } - } - - private class LocalUnsafe extends AbstractUnsafe { - - @Override - public void connect(final SocketAddress remoteAddress, - SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - if (state == 2) { - Exception cause = new AlreadyConnectedException(); - safeSetFailure(promise, cause); - pipeline().fireExceptionCaught(cause); - return; - } - - if (connectPromise != null) { - throw new ConnectionPendingException(); - } - - connectPromise = promise; - - if (state != 1) { - // Not bound yet and no localAddress specified - get one. - if (localAddress == null) { - localAddress = new LocalAddress(LocalChannel.this); - } - } - - if (localAddress != null) { - try { - doBind(localAddress); - } catch (Throwable t) { - safeSetFailure(promise, t); - close(voidPromise()); - return; - } - } - - Channel boundChannel = LocalChannelRegistry.get(remoteAddress); - if (!(boundChannel instanceof LocalServerChannel)) { - Exception cause = new ChannelException("connection refused"); - safeSetFailure(promise, cause); - close(voidPromise()); - return; - } - - LocalServerChannel serverChannel = (LocalServerChannel) boundChannel; - peer = serverChannel.serve(LocalChannel.this); - } - } -} diff --git a/java/src/game/net/channel/local/LocalChannelRegistry.java b/java/src/game/net/channel/local/LocalChannelRegistry.java deleted file mode 100644 index c646b5a..0000000 --- a/java/src/game/net/channel/local/LocalChannelRegistry.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.local; - -import java.net.SocketAddress; -import java.util.concurrent.ConcurrentMap; - -import game.net.channel.Channel; -import game.net.channel.ChannelException; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.StringUtil; - -final class LocalChannelRegistry { - - private static final ConcurrentMap boundChannels = PlatformDependent.newConcurrentHashMap(); - - static LocalAddress register( - Channel channel, LocalAddress oldLocalAddress, SocketAddress localAddress) { - if (oldLocalAddress != null) { - throw new ChannelException("already bound"); - } - if (!(localAddress instanceof LocalAddress)) { - throw new ChannelException("unsupported address type: " + StringUtil.simpleClassName(localAddress)); - } - - LocalAddress addr = (LocalAddress) localAddress; - if (LocalAddress.ANY.equals(addr)) { - addr = new LocalAddress(channel); - } - - Channel boundChannel = boundChannels.putIfAbsent(addr, channel); - if (boundChannel != null) { - throw new ChannelException("address already in use by: " + boundChannel); - } - return addr; - } - - static Channel get(SocketAddress localAddress) { - return boundChannels.get(localAddress); - } - - static void unregister(LocalAddress localAddress) { - boundChannels.remove(localAddress); - } - - private LocalChannelRegistry() { - // Unused - } -} diff --git a/java/src/game/net/channel/local/LocalEventLoop.java b/java/src/game/net/channel/local/LocalEventLoop.java deleted file mode 100644 index ee4a689..0000000 --- a/java/src/game/net/channel/local/LocalEventLoop.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.local; - -import java.util.concurrent.ThreadFactory; - -import game.net.channel.SingleThreadEventLoop; - -final class LocalEventLoop extends SingleThreadEventLoop { - - LocalEventLoop(LocalEventLoopGroup parent, ThreadFactory threadFactory) { - super(parent, threadFactory, true); - } - - @Override - protected void run() { - for (;;) { - Runnable task = takeTask(); - if (task != null) { - task.run(); - updateLastExecutionTime(); - } - - if (confirmShutdown()) { - break; - } - } - } -} diff --git a/java/src/game/net/channel/local/LocalEventLoopGroup.java b/java/src/game/net/channel/local/LocalEventLoopGroup.java deleted file mode 100644 index 0b2aefd..0000000 --- a/java/src/game/net/channel/local/LocalEventLoopGroup.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.local; - -import java.util.concurrent.ThreadFactory; - -import game.net.channel.MultithreadEventLoopGroup; -import game.net.util.concurrent.EventExecutor; - -/** - * {@link MultithreadEventLoopGroup} which must be used for the local transport. - */ -public class LocalEventLoopGroup extends MultithreadEventLoopGroup { - - /** - * Create a new instance with the default number of threads. - */ - public LocalEventLoopGroup() { - this(0); - } - - /** - * Create a new instance - * - * @param nThreads the number of threads to use - */ - public LocalEventLoopGroup(int nThreads) { - this(nThreads, null); - } - - /** - * Create a new instance - * - * @param nThreads the number of threads to use - * @param threadFactory the {@link ThreadFactory} or {@code null} to use the default - */ - public LocalEventLoopGroup(int nThreads, ThreadFactory threadFactory) { - super(nThreads, threadFactory); - } - - @Override - protected EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception { - return new LocalEventLoop(this, threadFactory); - } -} diff --git a/java/src/game/net/channel/local/LocalServerChannel.java b/java/src/game/net/channel/local/LocalServerChannel.java deleted file mode 100644 index ac01428..0000000 --- a/java/src/game/net/channel/local/LocalServerChannel.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.local; - -import java.net.SocketAddress; -import java.util.ArrayDeque; -import java.util.Queue; - -import game.net.channel.AbstractServerChannel; -import game.net.channel.ChannelConfig; -import game.net.channel.ChannelPipeline; -import game.net.channel.DefaultChannelConfig; -import game.net.channel.EventLoop; -import game.net.channel.SingleThreadEventLoop; -import game.net.util.concurrent.SingleThreadEventExecutor; - -/** - * A {@link ServerChannel} for the local transport which allows in VM communication. - */ -public class LocalServerChannel extends AbstractServerChannel { - - private final ChannelConfig config = new DefaultChannelConfig(this); - private final Queue inboundBuffer = new ArrayDeque(); - private final Runnable shutdownHook = new Runnable() { - @Override - public void run() { - unsafe().close(unsafe().voidPromise()); - } - }; - - private volatile int state; // 0 - open, 1 - active, 2 - closed - private volatile LocalAddress localAddress; - private volatile boolean acceptInProgress; - - @Override - public ChannelConfig config() { - return config; - } - - @Override - public LocalAddress localAddress() { - return (LocalAddress) super.localAddress(); - } - - @Override - public LocalAddress remoteAddress() { - return (LocalAddress) super.remoteAddress(); - } - - @Override - public boolean isOpen() { - return state < 2; - } - - @Override - public boolean isActive() { - return state == 1; - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof SingleThreadEventLoop; - } - - @Override - protected SocketAddress localAddress0() { - return localAddress; - } - - @Override - protected void doRegister() throws Exception { - ((SingleThreadEventExecutor) eventLoop()).addShutdownHook(shutdownHook); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - this.localAddress = LocalChannelRegistry.register(this, this.localAddress, localAddress); - state = 1; - } - - @Override - protected void doClose() throws Exception { - if (state <= 1) { - // Update all internal state before the closeFuture is notified. - if (localAddress != null) { - LocalChannelRegistry.unregister(localAddress); - localAddress = null; - } - state = 2; - } - } - - @Override - protected void doDeregister() throws Exception { - ((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook); - } - - @Override - protected void doBeginRead() throws Exception { - if (acceptInProgress) { - return; - } - - Queue inboundBuffer = this.inboundBuffer; - if (inboundBuffer.isEmpty()) { - acceptInProgress = true; - return; - } - - ChannelPipeline pipeline = pipeline(); - for (;;) { - Object m = inboundBuffer.poll(); - if (m == null) { - break; - } - pipeline.fireChannelRead(m); - } - pipeline.fireChannelReadComplete(); - } - - LocalChannel serve(final LocalChannel peer) { - final LocalChannel child = new LocalChannel(this, peer); - if (eventLoop().inEventLoop()) { - serve0(child); - } else { - eventLoop().execute(new Runnable() { - @Override - public void run() { - serve0(child); - } - }); - } - return child; - } - - private void serve0(final LocalChannel child) { - inboundBuffer.add(child); - if (acceptInProgress) { - acceptInProgress = false; - ChannelPipeline pipeline = pipeline(); - for (;;) { - Object m = inboundBuffer.poll(); - if (m == null) { - break; - } - pipeline.fireChannelRead(m); - } - pipeline.fireChannelReadComplete(); - } - } -} diff --git a/java/src/game/net/channel/nio/AbstractNioByteChannel.java b/java/src/game/net/channel/nio/AbstractNioByteChannel.java deleted file mode 100644 index 82ec982..0000000 --- a/java/src/game/net/channel/nio/AbstractNioByteChannel.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.nio; - -import java.io.IOException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; - -import game.net.buffer.ByteBuf; -import game.net.buffer.ByteBufAllocator; -import game.net.channel.Channel; -import game.net.channel.ChannelConfig; -import game.net.channel.ChannelOption; -import game.net.channel.ChannelOutboundBuffer; -import game.net.channel.ChannelPipeline; -import game.net.channel.RecvByteBufAllocator; -import game.net.channel.socket.ChannelInputShutdownEvent; -import game.net.util.internal.StringUtil; - -/** - * {@link AbstractNioChannel} base class for {@link Channel}s that operate on bytes. - */ -public abstract class AbstractNioByteChannel extends AbstractNioChannel { - - private static final String EXPECTED_TYPES = - " (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ')'; // ", " + -// StringUtil.simpleClassName(FileRegion.class) + ')'; - - private Runnable flushTask; - - /** - * Create a new instance - * - * @param parent the parent {@link Channel} by which this instance was created. May be {@code null} - * @param ch the underlying {@link SelectableChannel} on which it operates - */ - protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) { - super(parent, ch, SelectionKey.OP_READ); - } - - @Override - protected AbstractNioUnsafe newUnsafe() { - return new NioByteUnsafe(); - } - - private final class NioByteUnsafe extends AbstractNioUnsafe { - private RecvByteBufAllocator.Handle allocHandle; - - private void closeOnRead(ChannelPipeline pipeline) { - SelectionKey key = selectionKey(); - setInputShutdown(); - if (isOpen()) { - if (Boolean.TRUE.equals(config().getOption(ChannelOption.ALLOW_HALF_CLOSURE))) { - key.interestOps(key.interestOps() & ~readInterestOp); - pipeline.fireUserEventTriggered(ChannelInputShutdownEvent.INSTANCE); - } else { - close(voidPromise()); - } - } - } - - private void handleReadException(ChannelPipeline pipeline, - ByteBuf byteBuf, Throwable cause, boolean close) { - if (byteBuf != null) { - if (byteBuf.isReadable()) { - setReadPending(false); - pipeline.fireChannelRead(byteBuf); - } else { - byteBuf.release(); - } - } - pipeline.fireChannelReadComplete(); - pipeline.fireExceptionCaught(cause); - if (close || cause instanceof IOException) { - closeOnRead(pipeline); - } - } - - @Override - public void read() { - final ChannelConfig config = config(); - if (!config.isAutoRead() && !isReadPending()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - removeReadOp(); - return; - } - - final ChannelPipeline pipeline = pipeline(); - final ByteBufAllocator allocator = config.getAllocator(); - final int maxMessagesPerRead = config.getMaxMessagesPerRead(); - RecvByteBufAllocator.Handle allocHandle = this.allocHandle; - if (allocHandle == null) { - this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); - } - - ByteBuf byteBuf = null; - int messages = 0; - boolean close = false; - try { - int totalReadAmount = 0; - boolean readPendingReset = false; - do { - byteBuf = allocHandle.allocate(allocator); - int writable = byteBuf.writableBytes(); - int localReadAmount = doReadBytes(byteBuf); - if (localReadAmount <= 0) { - // not was read release the buffer - byteBuf.release(); - close = localReadAmount < 0; - break; - } - if (!readPendingReset) { - readPendingReset = true; - setReadPending(false); - } - pipeline.fireChannelRead(byteBuf); - byteBuf = null; - - if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) { - // Avoid overflow. - totalReadAmount = Integer.MAX_VALUE; - break; - } - - totalReadAmount += localReadAmount; - - // stop reading - if (!config.isAutoRead()) { - break; - } - - if (localReadAmount < writable) { - // Read less than what the buffer can hold, - // which might mean we drained the recv buffer completely. - break; - } - } while (++ messages < maxMessagesPerRead); - - pipeline.fireChannelReadComplete(); - allocHandle.record(totalReadAmount); - - if (close) { - closeOnRead(pipeline); - close = false; - } - } catch (Throwable t) { - handleReadException(pipeline, byteBuf, t, close); - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!config.isAutoRead() && !isReadPending()) { - removeReadOp(); - } - } - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - int writeSpinCount = -1; - - for (;;) { - Object msg = in.current(); - if (msg == null) { - // Wrote all messages. - clearOpWrite(); - break; - } - - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - in.remove(); - continue; - } - - boolean setOpWrite = false; - boolean done = false; - long flushedAmount = 0; - if (writeSpinCount == -1) { - writeSpinCount = config().getWriteSpinCount(); - } - for (int i = writeSpinCount - 1; i >= 0; i --) { - int localFlushedAmount = doWriteBytes(buf); - if (localFlushedAmount == 0) { - setOpWrite = true; - break; - } - - flushedAmount += localFlushedAmount; - if (!buf.isReadable()) { - done = true; - break; - } - } - - in.progress(flushedAmount); - - if (done) { - in.remove(); - } else { - incompleteWrite(setOpWrite); - break; - } - } -// else if (msg instanceof FileRegion) { -// FileRegion region = (FileRegion) msg; -// boolean setOpWrite = false; -// boolean done = false; -// long flushedAmount = 0; -// if (writeSpinCount == -1) { -// writeSpinCount = config().getWriteSpinCount(); -// } -// for (int i = writeSpinCount - 1; i >= 0; i --) { -// long localFlushedAmount = doWriteFileRegion(region); -// if (localFlushedAmount == 0) { -// setOpWrite = true; -// break; -// } -// -// flushedAmount += localFlushedAmount; -// if (region.transfered() >= region.count()) { -// done = true; -// break; -// } -// } -// -// in.progress(flushedAmount); -// -// if (done) { -// in.remove(); -// } else { -// incompleteWrite(setOpWrite); -// break; -// } -// } - else { - // Should not reach here. - throw new Error(); - } - } - } - - @Override - protected final Object filterOutboundMessage(Object msg) { - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - if (buf.isDirect()) { - return msg; - } - - return newDirectBuffer(buf); - } - -// if (msg instanceof FileRegion) { -// return msg; -// } - - throw new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES); - } - - protected final void incompleteWrite(boolean setOpWrite) { - // Did not write completely. - if (setOpWrite) { - setOpWrite(); - } else { - // Schedule flush again later so other tasks can be picked up in the meantime - Runnable flushTask = this.flushTask; - if (flushTask == null) { - flushTask = this.flushTask = new Runnable() { - @Override - public void run() { - flush(); - } - }; - } - eventLoop().execute(flushTask); - } - } - - /** - * Write a {@link FileRegion} - * - * @param region the {@link FileRegion} from which the bytes should be written - * @return amount the amount of written bytes - */ -// protected abstract long doWriteFileRegion(FileRegion region) throws Exception; - - /** - * Read bytes into the given {@link ByteBuf} and return the amount. - */ - protected abstract int doReadBytes(ByteBuf buf) throws Exception; - - /** - * Write bytes form the given {@link ByteBuf} to the underlying {@link java.nio.channels.Channel}. - * @param buf the {@link ByteBuf} from which the bytes should be written - * @return amount the amount of written bytes - */ - protected abstract int doWriteBytes(ByteBuf buf) throws Exception; - - protected final void setOpWrite() { - final SelectionKey key = selectionKey(); - // Check first if the key is still valid as it may be canceled as part of the deregistration - // from the EventLoop - // See https://github.com/netty/netty/issues/2104 - if (!key.isValid()) { - return; - } - final int interestOps = key.interestOps(); - if ((interestOps & SelectionKey.OP_WRITE) == 0) { - key.interestOps(interestOps | SelectionKey.OP_WRITE); - } - } - - protected final void clearOpWrite() { - final SelectionKey key = selectionKey(); - // Check first if the key is still valid as it may be canceled as part of the deregistration - // from the EventLoop - // See https://github.com/netty/netty/issues/2104 - if (!key.isValid()) { - return; - } - final int interestOps = key.interestOps(); - if ((interestOps & SelectionKey.OP_WRITE) != 0) { - key.interestOps(interestOps & ~SelectionKey.OP_WRITE); - } - } -} diff --git a/java/src/game/net/channel/nio/AbstractNioChannel.java b/java/src/game/net/channel/nio/AbstractNioChannel.java deleted file mode 100644 index 0b9dd43..0000000 --- a/java/src/game/net/channel/nio/AbstractNioChannel.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.nio; - -import java.io.IOException; -import java.net.ConnectException; -import java.net.SocketAddress; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import game.net.buffer.ByteBuf; -import game.net.buffer.ByteBufAllocator; -import game.net.buffer.ByteBufUtil; -import game.net.buffer.Unpooled; -import game.net.channel.AbstractChannel; -import game.net.channel.Channel; -import game.net.channel.ChannelException; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelFutureListener; -import game.net.channel.ChannelPromise; -import game.net.channel.ConnectTimeoutException; -import game.net.channel.EventLoop; -import game.net.util.ReferenceCountUtil; -import game.net.util.ReferenceCounted; -import game.net.util.internal.OneTimeTask; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Abstract base class for {@link Channel} implementations which use a Selector based approach. - */ -public abstract class AbstractNioChannel extends AbstractChannel { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(AbstractNioChannel.class); - - private final SelectableChannel ch; - protected final int readInterestOp; - volatile SelectionKey selectionKey; - private volatile boolean inputShutdown; - private volatile boolean readPending; - - /** - * The future of the current connection attempt. If not null, subsequent - * connection attempts will fail. - */ - private ChannelPromise connectPromise; - private ScheduledFuture connectTimeoutFuture; - private SocketAddress requestedRemoteAddress; - - /** - * Create a new instance - * - * @param parent the parent {@link Channel} by which this instance was created. May be {@code null} - * @param ch the underlying {@link SelectableChannel} on which it operates - * @param readInterestOp the ops to set to receive data from the {@link SelectableChannel} - */ - protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { - super(parent); - this.ch = ch; - this.readInterestOp = readInterestOp; - try { - ch.configureBlocking(false); - } catch (IOException e) { - try { - ch.close(); - } catch (IOException e2) { - if (logger.isWarnEnabled()) { - logger.warn( - "Failed to close a partially initialized socket.", e2); - } - } - - throw new ChannelException("Failed to enter non-blocking mode.", e); - } - } - - @Override - public boolean isOpen() { - return ch.isOpen(); - } - - @Override - public NioUnsafe unsafe() { - return (NioUnsafe) super.unsafe(); - } - - protected SelectableChannel javaChannel() { - return ch; - } - - @Override - public NioEventLoop eventLoop() { - return (NioEventLoop) super.eventLoop(); - } - - /** - * Return the current {@link SelectionKey} - */ - protected SelectionKey selectionKey() { - assert selectionKey != null; - return selectionKey; - } - - protected boolean isReadPending() { - return readPending; - } - - protected void setReadPending(boolean readPending) { - this.readPending = readPending; - } - - /** - * Return {@code true} if the input of this {@link Channel} is shutdown - */ - protected boolean isInputShutdown() { - return inputShutdown; - } - - /** - * Shutdown the input of this {@link Channel}. - */ - void setInputShutdown() { - inputShutdown = true; - } - - /** - * Special {@link Unsafe} sub-type which allows to access the underlying {@link SelectableChannel} - */ - public interface NioUnsafe extends Unsafe { - /** - * Return underlying {@link SelectableChannel} - */ - SelectableChannel ch(); - - /** - * Finish connect - */ - void finishConnect(); - - /** - * Read from underlying {@link SelectableChannel} - */ - void read(); - - void forceFlush(); - } - - protected abstract class AbstractNioUnsafe extends AbstractUnsafe implements NioUnsafe { - - protected final void removeReadOp() { - SelectionKey key = selectionKey(); - // Check first if the key is still valid as it may be canceled as part of the deregistration - // from the EventLoop - // See https://github.com/netty/netty/issues/2104 - if (!key.isValid()) { - return; - } - int interestOps = key.interestOps(); - if ((interestOps & readInterestOp) != 0) { - // only remove readInterestOp if needed - key.interestOps(interestOps & ~readInterestOp); - } - } - - @Override - public final SelectableChannel ch() { - return javaChannel(); - } - - @Override - public final void connect( - final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - try { - if (connectPromise != null) { - throw new IllegalStateException("connection attempt already made"); - } - - boolean wasActive = isActive(); - if (doConnect(remoteAddress, localAddress)) { - fulfillConnectPromise(promise, wasActive); - } else { - connectPromise = promise; - requestedRemoteAddress = remoteAddress; - - // Schedule connect timeout. - int connectTimeoutMillis = config().getConnectTimeoutMillis(); - if (connectTimeoutMillis > 0) { - connectTimeoutFuture = eventLoop().schedule(new OneTimeTask() { - @Override - public void run() { - ChannelPromise connectPromise = AbstractNioChannel.this.connectPromise; - ConnectTimeoutException cause = - new ConnectTimeoutException("connection timed out: " + remoteAddress); - if (connectPromise != null && connectPromise.tryFailure(cause)) { - close(voidPromise()); - } - } - }, connectTimeoutMillis, TimeUnit.MILLISECONDS); - } - - promise.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (future.isCancelled()) { - if (connectTimeoutFuture != null) { - connectTimeoutFuture.cancel(false); - } - connectPromise = null; - close(voidPromise()); - } - } - }); - } - } catch (Throwable t) { - if (t instanceof ConnectException) { - Throwable newT = new ConnectException(t.getMessage() + ": " + remoteAddress); - newT.setStackTrace(t.getStackTrace()); - t = newT; - } - promise.tryFailure(t); - closeIfClosed(); - } - } - - private void fulfillConnectPromise(ChannelPromise promise, boolean wasActive) { - if (promise == null) { - // Closed via cancellation and the promise has been notified already. - return; - } - - // trySuccess() will return false if a user cancelled the connection attempt. - boolean promiseSet = promise.trySuccess(); - - // Regardless if the connection attempt was cancelled, channelActive() event should be triggered, - // because what happened is what happened. - if (!wasActive && isActive()) { - pipeline().fireChannelActive(); - } - - // If a user cancelled the connection attempt, close the channel, which is followed by channelInactive(). - if (!promiseSet) { - close(voidPromise()); - } - } - - private void fulfillConnectPromise(ChannelPromise promise, Throwable cause) { - if (promise == null) { - // Closed via cancellation and the promise has been notified already. - return; - } - - // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(cause); - closeIfClosed(); - } - - @Override - public final void finishConnect() { - // Note this method is invoked by the event loop only if the connection attempt was - // neither cancelled nor timed out. - - assert eventLoop().inEventLoop(); - - try { - boolean wasActive = isActive(); - doFinishConnect(); - fulfillConnectPromise(connectPromise, wasActive); - } catch (Throwable t) { - if (t instanceof ConnectException) { - Throwable newT = new ConnectException(t.getMessage() + ": " + requestedRemoteAddress); - newT.setStackTrace(t.getStackTrace()); - t = newT; - } - - fulfillConnectPromise(connectPromise, t); - } finally { - // Check for null as the connectTimeoutFuture is only created if a connectTimeoutMillis > 0 is used - // See https://github.com/netty/netty/issues/1770 - if (connectTimeoutFuture != null) { - connectTimeoutFuture.cancel(false); - } - connectPromise = null; - } - } - - @Override - protected final void flush0() { - // Flush immediately only when there's no pending flush. - // If there's a pending flush operation, event loop will call forceFlush() later, - // and thus there's no need to call it now. - if (isFlushPending()) { - return; - } - super.flush0(); - } - - @Override - public final void forceFlush() { - // directly call super.flush0() to force a flush now - super.flush0(); - } - - private boolean isFlushPending() { - SelectionKey selectionKey = selectionKey(); - return selectionKey.isValid() && (selectionKey.interestOps() & SelectionKey.OP_WRITE) != 0; - } - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof NioEventLoop; - } - - @Override - protected void doRegister() throws Exception { - boolean selected = false; - for (;;) { - try { - selectionKey = javaChannel().register(eventLoop().selector, 0, this); - return; - } catch (CancelledKeyException e) { - if (!selected) { - // Force the Selector to select now as the "canceled" SelectionKey may still be - // cached and not removed because no Select.select(..) operation was called yet. - eventLoop().selectNow(); - selected = true; - } else { - // We forced a select operation on the selector before but the SelectionKey is still cached - // for whatever reason. JDK bug ? - throw e; - } - } - } - } - - @Override - protected void doDeregister() throws Exception { - eventLoop().cancel(selectionKey()); - } - - @Override - protected void doBeginRead() throws Exception { - // Channel.read() or ChannelHandlerContext.read() was called - if (inputShutdown) { - return; - } - - final SelectionKey selectionKey = this.selectionKey; - if (!selectionKey.isValid()) { - return; - } - - readPending = true; - - final int interestOps = selectionKey.interestOps(); - if ((interestOps & readInterestOp) == 0) { - selectionKey.interestOps(interestOps | readInterestOp); - } - } - - /** - * Connect to the remote peer - */ - protected abstract boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception; - - /** - * Finish the connect - */ - protected abstract void doFinishConnect() throws Exception; - - /** - * Returns an off-heap copy of the specified {@link ByteBuf}, and releases the original one. - * Note that this method does not create an off-heap copy if the allocation / deallocation cost is too high, - * but just returns the original {@link ByteBuf}.. - */ - protected final ByteBuf newDirectBuffer(ByteBuf buf) { - final int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - ReferenceCountUtil.safeRelease(buf); - return Unpooled.EMPTY_BUFFER; - } - - final ByteBufAllocator alloc = alloc(); - if (alloc.isDirectBufferPooled()) { - ByteBuf directBuf = alloc.directBuffer(readableBytes); - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(buf); - return directBuf; - } - - final ByteBuf directBuf = ByteBufUtil.threadLocalDirectBuffer(); - if (directBuf != null) { - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(buf); - return directBuf; - } - - // Allocating and deallocating an unpooled direct buffer is very expensive; give up. - return buf; - } - - /** - * Returns an off-heap copy of the specified {@link ByteBuf}, and releases the specified holder. - * The caller must ensure that the holder releases the original {@link ByteBuf} when the holder is released by - * this method. Note that this method does not create an off-heap copy if the allocation / deallocation cost is - * too high, but just returns the original {@link ByteBuf}.. - */ - protected final ByteBuf newDirectBuffer(ReferenceCounted holder, ByteBuf buf) { - final int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - ReferenceCountUtil.safeRelease(holder); - return Unpooled.EMPTY_BUFFER; - } - - final ByteBufAllocator alloc = alloc(); - if (alloc.isDirectBufferPooled()) { - ByteBuf directBuf = alloc.directBuffer(readableBytes); - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(holder); - return directBuf; - } - - final ByteBuf directBuf = ByteBufUtil.threadLocalDirectBuffer(); - if (directBuf != null) { - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(holder); - return directBuf; - } - - // Allocating and deallocating an unpooled direct buffer is very expensive; give up. - if (holder != buf) { - // Ensure to call holder.release() to give the holder a chance to release other resources than its content. - buf.retain(); - ReferenceCountUtil.safeRelease(holder); - } - - return buf; - } -} diff --git a/java/src/game/net/channel/nio/AbstractNioMessageChannel.java b/java/src/game/net/channel/nio/AbstractNioMessageChannel.java deleted file mode 100644 index 2e87f77..0000000 --- a/java/src/game/net/channel/nio/AbstractNioMessageChannel.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.nio; - -import java.io.IOException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.util.ArrayList; -import java.util.List; - -import game.net.channel.Channel; -import game.net.channel.ChannelConfig; -import game.net.channel.ChannelOutboundBuffer; -import game.net.channel.ChannelPipeline; -import game.net.channel.ServerChannel; - -/** - * {@link AbstractNioChannel} base class for {@link Channel}s that operate on messages. - */ -public abstract class AbstractNioMessageChannel extends AbstractNioChannel { - - /** - * @see {@link AbstractNioChannel#AbstractNioChannel(Channel, SelectableChannel, int)} - */ - protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) { - super(parent, ch, readInterestOp); - } - - @Override - protected AbstractNioUnsafe newUnsafe() { - return new NioMessageUnsafe(); - } - - private final class NioMessageUnsafe extends AbstractNioUnsafe { - - private final List readBuf = new ArrayList(); - - @Override - public void read() { - assert eventLoop().inEventLoop(); - final ChannelConfig config = config(); - if (!config.isAutoRead() && !isReadPending()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - removeReadOp(); - return; - } - - final int maxMessagesPerRead = config.getMaxMessagesPerRead(); - final ChannelPipeline pipeline = pipeline(); - boolean closed = false; - Throwable exception = null; - try { - try { - for (;;) { - int localRead = doReadMessages(readBuf); - if (localRead == 0) { - break; - } - if (localRead < 0) { - closed = true; - break; - } - - // stop reading and remove op - if (!config.isAutoRead()) { - break; - } - - if (readBuf.size() >= maxMessagesPerRead) { - break; - } - } - } catch (Throwable t) { - exception = t; - } - setReadPending(false); - int size = readBuf.size(); - for (int i = 0; i < size; i ++) { - pipeline.fireChannelRead(readBuf.get(i)); - } - - readBuf.clear(); - pipeline.fireChannelReadComplete(); - - if (exception != null) { - if (exception instanceof IOException) { - // ServerChannel should not be closed even on IOException because it can often continue - // accepting incoming connections. (e.g. too many open files) - closed = !(AbstractNioMessageChannel.this instanceof ServerChannel); - } - - pipeline.fireExceptionCaught(exception); - } - - if (closed) { - if (isOpen()) { - close(voidPromise()); - } - } - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!config.isAutoRead() && !isReadPending()) { - removeReadOp(); - } - } - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - final SelectionKey key = selectionKey(); - final int interestOps = key.interestOps(); - - for (;;) { - Object msg = in.current(); - if (msg == null) { - // Wrote all messages. - if ((interestOps & SelectionKey.OP_WRITE) != 0) { - key.interestOps(interestOps & ~SelectionKey.OP_WRITE); - } - break; - } - try { - boolean done = false; - for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) { - if (doWriteMessage(msg, in)) { - done = true; - break; - } - } - - if (done) { - in.remove(); - } else { - // Did not write all messages. - if ((interestOps & SelectionKey.OP_WRITE) == 0) { - key.interestOps(interestOps | SelectionKey.OP_WRITE); - } - break; - } - } catch (IOException e) { - if (continueOnWriteError()) { - in.remove(e); - } else { - throw e; - } - } - } - } - - /** - * Returns {@code true} if we should continue the write loop on a write error. - */ - protected boolean continueOnWriteError() { - return false; - } - - /** - * Read messages into the given array and return the amount which was read. - */ - protected abstract int doReadMessages(List buf) throws Exception; - - /** - * Write a message to the underlying {@link java.nio.channels.Channel}. - * - * @return {@code true} if and only if the message has been written - */ - protected abstract boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception; -} diff --git a/java/src/game/net/channel/nio/NioEventLoop.java b/java/src/game/net/channel/nio/NioEventLoop.java deleted file mode 100644 index 138f61d..0000000 --- a/java/src/game/net/channel/nio/NioEventLoop.java +++ /dev/null @@ -1,691 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.nio; - - -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.spi.SelectorProvider; -import java.util.ArrayList; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import game.net.channel.ChannelException; -import game.net.channel.EventLoopException; -import game.net.channel.SingleThreadEventLoop; -import game.net.channel.nio.AbstractNioChannel.NioUnsafe; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.SystemPropertyUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * {@link SingleThreadEventLoop} implementation which register the {@link Channel}'s to a - * {@link Selector} and so does the multi-plexing of these in the event loop. - * - */ -public final class NioEventLoop extends SingleThreadEventLoop { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioEventLoop.class); - - private static final int CLEANUP_INTERVAL = 256; // XXX Hard-coded value, but won't need customization. - - private static final boolean DISABLE_KEYSET_OPTIMIZATION = - SystemPropertyUtil.getBoolean("io.netty.noKeySetOptimization", false); - - private static final int MIN_PREMATURE_SELECTOR_RETURNS = 3; - private static final int SELECTOR_AUTO_REBUILD_THRESHOLD; - - // Workaround for JDK NIO bug. - // - // See: - // - http://bugs.sun.com/view_bug.do?bug_id=6427854 - // - https://github.com/netty/netty/issues/203 - static { - String key = "sun.nio.ch.bugLevel"; - try { - String buglevel = SystemPropertyUtil.get(key); - if (buglevel == null) { - System.setProperty(key, ""); - } - } catch (SecurityException e) { - if (logger.isDebugEnabled()) { - logger.debug("Unable to get/set System Property: {}", key, e); - } - } - - int selectorAutoRebuildThreshold = SystemPropertyUtil.getInt("io.netty.selectorAutoRebuildThreshold", 512); - if (selectorAutoRebuildThreshold < MIN_PREMATURE_SELECTOR_RETURNS) { - selectorAutoRebuildThreshold = 0; - } - - SELECTOR_AUTO_REBUILD_THRESHOLD = selectorAutoRebuildThreshold; - - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.noKeySetOptimization: {}", DISABLE_KEYSET_OPTIMIZATION); - logger.debug("-Dio.netty.selectorAutoRebuildThreshold: {}", SELECTOR_AUTO_REBUILD_THRESHOLD); - } - } - - /** - * The NIO {@link Selector}. - */ - Selector selector; - private SelectedSelectionKeySet selectedKeys; - - private final SelectorProvider provider; - - /** - * Boolean that controls determines if a blocked Selector.select should - * break out of its selection process. In our case we use a timeout for - * the select method and the select method will block for that time unless - * waken up. - */ - private final AtomicBoolean wakenUp = new AtomicBoolean(); - - private volatile int ioRatio = 50; - private int cancelledKeys; - private boolean needsToSelectAgain; - - NioEventLoop(NioEventLoopGroup parent, ThreadFactory threadFactory, SelectorProvider selectorProvider) { - super(parent, threadFactory, false); - if (selectorProvider == null) { - throw new NullPointerException("selectorProvider"); - } - provider = selectorProvider; - selector = openSelector(); - } - - private Selector openSelector() { - final Selector selector; - try { - selector = provider.openSelector(); - } catch (IOException e) { - throw new ChannelException("failed to open a new selector", e); - } - - if (DISABLE_KEYSET_OPTIMIZATION) { - return selector; - } - - try { - SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet(); - - Class selectorImplClass = - Class.forName("sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader()); - - // Ensure the current selector implementation is what we can instrument. - if (!selectorImplClass.isAssignableFrom(selector.getClass())) { - return selector; - } - - Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); - Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys"); - - selectedKeysField.setAccessible(true); - publicSelectedKeysField.setAccessible(true); - - selectedKeysField.set(selector, selectedKeySet); - publicSelectedKeysField.set(selector, selectedKeySet); - - selectedKeys = selectedKeySet; - logger.trace("Instrumented an optimized java.util.Set into: {}", selector); - } catch (Throwable t) { - selectedKeys = null; - logger.trace("Failed to instrument an optimized java.util.Set into: {}", selector, t); - } - - return selector; - } - - @Override - protected Queue newTaskQueue() { - // This event loop never calls takeTask() - return PlatformDependent.newMpscQueue(); - } - - /** - * Registers an arbitrary {@link SelectableChannel}, not necessarily created by Netty, to the {@link Selector} - * of this event loop. Once the specified {@link SelectableChannel} is registered, the specified {@code task} will - * be executed by this event loop when the {@link SelectableChannel} is ready. - */ - public void register(final SelectableChannel ch, final int interestOps, final NioTask task) { - if (ch == null) { - throw new NullPointerException("ch"); - } - if (interestOps == 0) { - throw new IllegalArgumentException("interestOps must be non-zero."); - } - if ((interestOps & ~ch.validOps()) != 0) { - throw new IllegalArgumentException( - "invalid interestOps: " + interestOps + "(validOps: " + ch.validOps() + ')'); - } - if (task == null) { - throw new NullPointerException("task"); - } - - if (isShutdown()) { - throw new IllegalStateException("event loop shut down"); - } - - try { - ch.register(selector, interestOps, task); - } catch (Exception e) { - throw new EventLoopException("failed to register a channel", e); - } - } - - /** - * Returns the percentage of the desired amount of time spent for I/O in the event loop. - */ - public int getIoRatio() { - return ioRatio; - } - - /** - * Sets the percentage of the desired amount of time spent for I/O in the event loop. The default value is - * {@code 50}, which means the event loop will try to spend the same amount of time for I/O as for non-I/O tasks. - */ - public void setIoRatio(int ioRatio) { - if (ioRatio <= 0 || ioRatio > 100) { - throw new IllegalArgumentException("ioRatio: " + ioRatio + " (expected: 0 < ioRatio <= 100)"); - } - this.ioRatio = ioRatio; - } - - /** - * Replaces the current {@link Selector} of this event loop with newly created {@link Selector}s to work - * around the infamous epoll 100% CPU bug. - */ - public void rebuildSelector() { - if (!inEventLoop()) { - execute(new Runnable() { - @Override - public void run() { - rebuildSelector(); - } - }); - return; - } - - final Selector oldSelector = selector; - final Selector newSelector; - - if (oldSelector == null) { - return; - } - - try { - newSelector = openSelector(); - } catch (Exception e) { - logger.warn("Failed to create a new Selector.", e); - return; - } - - // Register all channels to the new Selector. - int nChannels = 0; - for (;;) { - try { - for (SelectionKey key: oldSelector.keys()) { - Object a = key.attachment(); - try { - if (!key.isValid() || key.channel().keyFor(newSelector) != null) { - continue; - } - - int interestOps = key.interestOps(); - key.cancel(); - SelectionKey newKey = key.channel().register(newSelector, interestOps, a); - if (a instanceof AbstractNioChannel) { - // Update SelectionKey - ((AbstractNioChannel) a).selectionKey = newKey; - } - nChannels ++; - } catch (Exception e) { - logger.warn("Failed to re-register a Channel to the new Selector.", e); - if (a instanceof AbstractNioChannel) { - AbstractNioChannel ch = (AbstractNioChannel) a; - ch.unsafe().close(ch.unsafe().voidPromise()); - } else { - - NioTask task = (NioTask) a; - invokeChannelUnregistered(task, key, e); - } - } - } - } catch (ConcurrentModificationException e) { - // Probably due to concurrent modification of the key set. - continue; - } - - break; - } - - selector = newSelector; - - try { - // time to close the old selector as everything else is registered to the new one - oldSelector.close(); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to close the old Selector.", t); - } - } - - logger.info("Migrated " + nChannels + " channel(s) to the new Selector."); - } - - @Override - protected void run() { - for (;;) { - boolean oldWakenUp = wakenUp.getAndSet(false); - try { - if (hasTasks()) { - selectNow(); - } else { - select(oldWakenUp); - - // 'wakenUp.compareAndSet(false, true)' is always evaluated - // before calling 'selector.wakeup()' to reduce the wake-up - // overhead. (Selector.wakeup() is an expensive operation.) - // - // However, there is a race condition in this approach. - // The race condition is triggered when 'wakenUp' is set to - // true too early. - // - // 'wakenUp' is set to true too early if: - // 1) Selector is waken up between 'wakenUp.set(false)' and - // 'selector.select(...)'. (BAD) - // 2) Selector is waken up between 'selector.select(...)' and - // 'if (wakenUp.get()) { ... }'. (OK) - // - // In the first case, 'wakenUp' is set to true and the - // following 'selector.select(...)' will wake up immediately. - // Until 'wakenUp' is set to false again in the next round, - // 'wakenUp.compareAndSet(false, true)' will fail, and therefore - // any attempt to wake up the Selector will fail, too, causing - // the following 'selector.select(...)' call to block - // unnecessarily. - // - // To fix this problem, we wake up the selector again if wakenUp - // is true immediately after selector.select(...). - // It is inefficient in that it wakes up the selector for both - // the first case (BAD - wake-up required) and the second case - // (OK - no wake-up required). - - if (wakenUp.get()) { - selector.wakeup(); - } - } - - cancelledKeys = 0; - needsToSelectAgain = false; - final int ioRatio = this.ioRatio; - if (ioRatio == 100) { - processSelectedKeys(); - runAllTasks(); - } else { - final long ioStartTime = System.nanoTime(); - - processSelectedKeys(); - - final long ioTime = System.nanoTime() - ioStartTime; - runAllTasks(ioTime * (100 - ioRatio) / ioRatio); - } - - if (isShuttingDown()) { - closeAll(); - if (confirmShutdown()) { - break; - } - } - } catch (Throwable t) { - logger.warn("Unexpected exception in the selector loop.", t); - - // Prevent possible consecutive immediate failures that lead to - // excessive CPU consumption. - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore. - } - } - } - } - - private void processSelectedKeys() { - if (selectedKeys != null) { - processSelectedKeysOptimized(selectedKeys.flip()); - } else { - processSelectedKeysPlain(selector.selectedKeys()); - } - } - - @Override - protected void cleanup() { - try { - selector.close(); - } catch (IOException e) { - logger.warn("Failed to close a selector.", e); - } - } - - void cancel(SelectionKey key) { - key.cancel(); - cancelledKeys ++; - if (cancelledKeys >= CLEANUP_INTERVAL) { - cancelledKeys = 0; - needsToSelectAgain = true; - } - } - - @Override - protected Runnable pollTask() { - Runnable task = super.pollTask(); - if (needsToSelectAgain) { - selectAgain(); - } - return task; - } - - private void processSelectedKeysPlain(Set selectedKeys) { - // check if the set is empty and if so just return to not create garbage by - // creating a new Iterator every time even if there is nothing to process. - // See https://github.com/netty/netty/issues/597 - if (selectedKeys.isEmpty()) { - return; - } - - Iterator i = selectedKeys.iterator(); - for (;;) { - final SelectionKey k = i.next(); - final Object a = k.attachment(); - i.remove(); - - if (a instanceof AbstractNioChannel) { - processSelectedKey(k, (AbstractNioChannel) a); - } else { - - NioTask task = (NioTask) a; - processSelectedKey(k, task); - } - - if (!i.hasNext()) { - break; - } - - if (needsToSelectAgain) { - selectAgain(); - selectedKeys = selector.selectedKeys(); - - // Create the iterator again to avoid ConcurrentModificationException - if (selectedKeys.isEmpty()) { - break; - } else { - i = selectedKeys.iterator(); - } - } - } - } - - private void processSelectedKeysOptimized(SelectionKey[] selectedKeys) { - for (int i = 0;; i ++) { - final SelectionKey k = selectedKeys[i]; - if (k == null) { - break; - } - // null out entry in the array to allow to have it GC'ed once the Channel close - // See https://github.com/netty/netty/issues/2363 - selectedKeys[i] = null; - - final Object a = k.attachment(); - - if (a instanceof AbstractNioChannel) { - processSelectedKey(k, (AbstractNioChannel) a); - } else { - - NioTask task = (NioTask) a; - processSelectedKey(k, task); - } - - if (needsToSelectAgain) { - // null out entries in the array to allow to have it GC'ed once the Channel close - // See https://github.com/netty/netty/issues/2363 - for (;;) { - if (selectedKeys[i] == null) { - break; - } - selectedKeys[i] = null; - i++; - } - - selectAgain(); - // Need to flip the optimized selectedKeys to get the right reference to the array - // and reset the index to -1 which will then set to 0 on the for loop - // to start over again. - // - // See https://github.com/netty/netty/issues/1523 - selectedKeys = this.selectedKeys.flip(); - i = -1; - } - } - } - - private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { - final NioUnsafe unsafe = ch.unsafe(); - if (!k.isValid()) { - // close the channel if the key is not valid anymore - unsafe.close(unsafe.voidPromise()); - return; - } - - try { - int readyOps = k.readyOps(); - // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead - // to a spin loop - if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) { - unsafe.read(); - if (!ch.isOpen()) { - // Connection already closed - no need to handle write. - return; - } - } - if ((readyOps & SelectionKey.OP_WRITE) != 0) { - // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write - ch.unsafe().forceFlush(); - } - if ((readyOps & SelectionKey.OP_CONNECT) != 0) { - // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking - // See https://github.com/netty/netty/issues/924 - int ops = k.interestOps(); - ops &= ~SelectionKey.OP_CONNECT; - k.interestOps(ops); - - unsafe.finishConnect(); - } - } catch (CancelledKeyException ignored) { - unsafe.close(unsafe.voidPromise()); - } - } - - private static void processSelectedKey(SelectionKey k, NioTask task) { - int state = 0; - try { - task.channelReady(k.channel(), k); - state = 1; - } catch (Exception e) { - k.cancel(); - invokeChannelUnregistered(task, k, e); - state = 2; - } finally { - switch (state) { - case 0: - k.cancel(); - invokeChannelUnregistered(task, k, null); - break; - case 1: - if (!k.isValid()) { // Cancelled by channelReady() - invokeChannelUnregistered(task, k, null); - } - break; - } - } - } - - private void closeAll() { - selectAgain(); - Set keys = selector.keys(); - Collection channels = new ArrayList(keys.size()); - for (SelectionKey k: keys) { - Object a = k.attachment(); - if (a instanceof AbstractNioChannel) { - channels.add((AbstractNioChannel) a); - } else { - k.cancel(); - - NioTask task = (NioTask) a; - invokeChannelUnregistered(task, k, null); - } - } - - for (AbstractNioChannel ch: channels) { - ch.unsafe().close(ch.unsafe().voidPromise()); - } - } - - private static void invokeChannelUnregistered(NioTask task, SelectionKey k, Throwable cause) { - try { - task.channelUnregistered(k.channel(), cause); - } catch (Exception e) { - logger.warn("Unexpected exception while running NioTask.channelUnregistered()", e); - } - } - - @Override - protected void wakeup(boolean inEventLoop) { - if (!inEventLoop && wakenUp.compareAndSet(false, true)) { - selector.wakeup(); - } - } - - void selectNow() throws IOException { - try { - selector.selectNow(); - } finally { - // restore wakup state if needed - if (wakenUp.get()) { - selector.wakeup(); - } - } - } - - private void select(boolean oldWakenUp) throws IOException { - Selector selector = this.selector; - try { - int selectCnt = 0; - long currentTimeNanos = System.nanoTime(); - long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos); - for (;;) { - long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L; - if (timeoutMillis <= 0) { - if (selectCnt == 0) { - selector.selectNow(); - selectCnt = 1; - } - break; - } - - int selectedKeys = selector.select(timeoutMillis); - selectCnt ++; - - if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) { - // - Selected something, - // - waken up by user, or - // - the task queue has a pending task. - // - a scheduled task is ready for processing - break; - } - if (Thread.interrupted()) { - // Thread was interrupted so reset selected keys and break so we not run into a busy loop. - // As this is most likely a bug in the handler of the user or it's client library we will - // also log it. - // - // See https://github.com/netty/netty/issues/2426 - if (logger.isDebugEnabled()) { - logger.debug("Selector.select() returned prematurely because " + - "Thread.currentThread().interrupt() was called. Use " + - "NioEventLoop.shutdownGracefully() to shutdown the NioEventLoop."); - } - selectCnt = 1; - break; - } - - long time = System.nanoTime(); - if (time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos) { - // timeoutMillis elapsed without anything selected. - selectCnt = 1; - } else if (SELECTOR_AUTO_REBUILD_THRESHOLD > 0 && - selectCnt >= SELECTOR_AUTO_REBUILD_THRESHOLD) { - // The selector returned prematurely many times in a row. - // Rebuild the selector to work around the problem. - logger.warn( - "Selector.select() returned prematurely {} times in a row; rebuilding selector.", - selectCnt); - - rebuildSelector(); - selector = this.selector; - - // Select again to populate selectedKeys. - selector.selectNow(); - selectCnt = 1; - break; - } - - currentTimeNanos = time; - } - - if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS) { - if (logger.isDebugEnabled()) { - logger.debug("Selector.select() returned prematurely {} times in a row.", selectCnt - 1); - } - } - } catch (CancelledKeyException e) { - if (logger.isDebugEnabled()) { - logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector - JDK bug?", e); - } - // Harmless exception - log anyway - } - } - - private void selectAgain() { - needsToSelectAgain = false; - try { - selector.selectNow(); - } catch (Throwable t) { - logger.warn("Failed to update SelectionKeys.", t); - } - } -} diff --git a/java/src/game/net/channel/nio/NioEventLoopGroup.java b/java/src/game/net/channel/nio/NioEventLoopGroup.java deleted file mode 100644 index 169eae5..0000000 --- a/java/src/game/net/channel/nio/NioEventLoopGroup.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.nio; - -import java.nio.channels.spi.SelectorProvider; -import java.util.concurrent.ThreadFactory; - -import game.net.channel.MultithreadEventLoopGroup; -import game.net.util.concurrent.EventExecutor; - -/** - * {@link MultithreadEventLoopGroup} implementations which is used for NIO {@link Selector} based {@link Channel}s. - */ -public class NioEventLoopGroup extends MultithreadEventLoopGroup { - - /** - * Create a new instance using the default number of threads, the default {@link ThreadFactory} and - * the {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}. - */ - public NioEventLoopGroup() { - this(0); - } - - /** - * Create a new instance using the specified number of threads, {@link ThreadFactory} and the - * {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}. - */ - public NioEventLoopGroup(int nThreads) { - this(nThreads, null); - } - - /** - * Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the - * {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}. - */ - public NioEventLoopGroup(int nThreads, ThreadFactory threadFactory) { - this(nThreads, threadFactory, SelectorProvider.provider()); - } - - /** - * Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the given - * {@link SelectorProvider}. - */ - public NioEventLoopGroup( - int nThreads, ThreadFactory threadFactory, final SelectorProvider selectorProvider) { - super(nThreads, threadFactory, selectorProvider); - } - - /** - * Sets the percentage of the desired amount of time spent for I/O in the child event loops. The default value is - * {@code 50}, which means the event loop will try to spend the same amount of time for I/O as for non-I/O tasks. - */ - public void setIoRatio(int ioRatio) { - for (EventExecutor e: children()) { - ((NioEventLoop) e).setIoRatio(ioRatio); - } - } - - /** - * Replaces the current {@link Selector}s of the child event loops with newly created {@link Selector}s to work - * around the infamous epoll 100% CPU bug. - */ - public void rebuildSelectors() { - for (EventExecutor e: children()) { - ((NioEventLoop) e).rebuildSelector(); - } - } - - @Override - protected EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception { - return new NioEventLoop(this, threadFactory, (SelectorProvider) args[0]); - } -} diff --git a/java/src/game/net/channel/nio/NioTask.java b/java/src/game/net/channel/nio/NioTask.java deleted file mode 100644 index 7bfa9e2..0000000 --- a/java/src/game/net/channel/nio/NioTask.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.nio; - -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; - -/** - * An arbitrary task that can be executed by {@link NioEventLoop} when a {@link SelectableChannel} becomes ready. - * - * @see NioEventLoop#register(SelectableChannel, int, NioTask) - */ -public interface NioTask { - /** - * Invoked when the {@link SelectableChannel} has been selected by the {@link Selector}. - */ - void channelReady(C ch, SelectionKey key) throws Exception; - - /** - * Invoked when the {@link SelectionKey} of the specified {@link SelectableChannel} has been cancelled and thus - * this {@link NioTask} will not be notified anymore. - * - * @param cause the cause of the unregistration. {@code null} if a user called {@link SelectionKey#cancel()} or - * the event loop has been shut down. - */ - void channelUnregistered(C ch, Throwable cause) throws Exception; -} diff --git a/java/src/game/net/channel/nio/SelectedSelectionKeySet.java b/java/src/game/net/channel/nio/SelectedSelectionKeySet.java deleted file mode 100644 index 22441b7..0000000 --- a/java/src/game/net/channel/nio/SelectedSelectionKeySet.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.channel.nio; - -import java.nio.channels.SelectionKey; -import java.util.AbstractSet; -import java.util.Iterator; - -final class SelectedSelectionKeySet extends AbstractSet { - - private SelectionKey[] keysA; - private int keysASize; - private SelectionKey[] keysB; - private int keysBSize; - private boolean isA = true; - - SelectedSelectionKeySet() { - keysA = new SelectionKey[1024]; - keysB = keysA.clone(); - } - - @Override - public boolean add(SelectionKey o) { - if (o == null) { - return false; - } - - if (isA) { - int size = keysASize; - keysA[size ++] = o; - keysASize = size; - if (size == keysA.length) { - doubleCapacityA(); - } - } else { - int size = keysBSize; - keysB[size ++] = o; - keysBSize = size; - if (size == keysB.length) { - doubleCapacityB(); - } - } - - return true; - } - - private void doubleCapacityA() { - SelectionKey[] newKeysA = new SelectionKey[keysA.length << 1]; - System.arraycopy(keysA, 0, newKeysA, 0, keysASize); - keysA = newKeysA; - } - - private void doubleCapacityB() { - SelectionKey[] newKeysB = new SelectionKey[keysB.length << 1]; - System.arraycopy(keysB, 0, newKeysB, 0, keysBSize); - keysB = newKeysB; - } - - SelectionKey[] flip() { - if (isA) { - isA = false; - keysA[keysASize] = null; - keysBSize = 0; - return keysA; - } else { - isA = true; - keysB[keysBSize] = null; - keysASize = 0; - return keysB; - } - } - - @Override - public int size() { - if (isA) { - return keysASize; - } else { - return keysBSize; - } - } - - @Override - public boolean remove(Object o) { - return false; - } - - @Override - public boolean contains(Object o) { - return false; - } - - @Override - public Iterator iterator() { - throw new UnsupportedOperationException(); - } -} diff --git a/java/src/game/net/channel/socket/ChannelInputShutdownEvent.java b/java/src/game/net/channel/socket/ChannelInputShutdownEvent.java deleted file mode 100644 index 5c61546..0000000 --- a/java/src/game/net/channel/socket/ChannelInputShutdownEvent.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket; - -/** - * Special event which will be fired and passed to the - * {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} methods once the input of - * a {@link SocketChannel} was shutdown and the {@link SocketChannelConfig#isAllowHalfClosure()} method returns - * {@code true}. - */ -public final class ChannelInputShutdownEvent { - - /** - * Instance to use - */ - - public static final ChannelInputShutdownEvent INSTANCE = new ChannelInputShutdownEvent(); - - private ChannelInputShutdownEvent() { } -} diff --git a/java/src/game/net/channel/socket/DefaultServerSocketChannelConfig.java b/java/src/game/net/channel/socket/DefaultServerSocketChannelConfig.java deleted file mode 100644 index 8700611..0000000 --- a/java/src/game/net/channel/socket/DefaultServerSocketChannelConfig.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket; - -import static game.net.channel.ChannelOption.SO_BACKLOG; -import static game.net.channel.ChannelOption.SO_RCVBUF; -import static game.net.channel.ChannelOption.SO_REUSEADDR; - -import java.net.ServerSocket; -import java.net.SocketException; -import java.util.Map; - -import game.net.buffer.ByteBufAllocator; -import game.net.channel.ChannelException; -import game.net.channel.ChannelOption; -import game.net.channel.DefaultChannelConfig; -import game.net.channel.MessageSizeEstimator; -import game.net.channel.RecvByteBufAllocator; -import game.net.util.NetUtil; - -/** - * The default {@link ServerSocketChannelConfig} implementation. - */ -public class DefaultServerSocketChannelConfig extends DefaultChannelConfig - implements ServerSocketChannelConfig { - - protected final ServerSocket javaSocket; - private volatile int backlog = NetUtil.SOMAXCONN; - - /** - * Creates a new instance. - */ - public DefaultServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) { - super(channel); - if (javaSocket == null) { - throw new NullPointerException("javaSocket"); - } - this.javaSocket = javaSocket; - } - - @Override - public Map, Object> getOptions() { - return getOptions(super.getOptions(), SO_RCVBUF, SO_REUSEADDR, SO_BACKLOG); - } - - - @Override - public T getOption(ChannelOption option) { - if (option == SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == SO_BACKLOG) { - return (T) Integer.valueOf(getBacklog()); - } - - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == SO_BACKLOG) { - setBacklog((Integer) value); - } else { - return super.setOption(option, value); - } - - return true; - } - - @Override - public boolean isReuseAddress() { - try { - return javaSocket.getReuseAddress(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public ServerSocketChannelConfig setReuseAddress(boolean reuseAddress) { - try { - javaSocket.setReuseAddress(reuseAddress); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public int getReceiveBufferSize() { - try { - return javaSocket.getReceiveBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public ServerSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - try { - javaSocket.setReceiveBufferSize(receiveBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public ServerSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth) { - javaSocket.setPerformancePreferences(connectionTime, latency, bandwidth); - return this; - } - - @Override - public int getBacklog() { - return backlog; - } - - @Override - public ServerSocketChannelConfig setBacklog(int backlog) { - if (backlog < 0) { - throw new IllegalArgumentException("backlog: " + backlog); - } - this.backlog = backlog; - return this; - } - - @Override - public ServerSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public ServerSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public ServerSocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public ServerSocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public ServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public ServerSocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public ServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public ServerSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public ServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } -} diff --git a/java/src/game/net/channel/socket/DefaultSocketChannelConfig.java b/java/src/game/net/channel/socket/DefaultSocketChannelConfig.java deleted file mode 100644 index 7d2d4a6..0000000 --- a/java/src/game/net/channel/socket/DefaultSocketChannelConfig.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket; - -import static game.net.channel.ChannelOption.ALLOW_HALF_CLOSURE; -import static game.net.channel.ChannelOption.IP_TOS; -import static game.net.channel.ChannelOption.SO_KEEPALIVE; -import static game.net.channel.ChannelOption.SO_LINGER; -import static game.net.channel.ChannelOption.SO_RCVBUF; -import static game.net.channel.ChannelOption.SO_REUSEADDR; -import static game.net.channel.ChannelOption.SO_SNDBUF; -import static game.net.channel.ChannelOption.TCP_NODELAY; - -import java.net.Socket; -import java.net.SocketException; -import java.util.Map; - -import game.net.buffer.ByteBufAllocator; -import game.net.channel.ChannelException; -import game.net.channel.ChannelOption; -import game.net.channel.DefaultChannelConfig; -import game.net.channel.MessageSizeEstimator; -import game.net.channel.RecvByteBufAllocator; -import game.net.util.internal.PlatformDependent; - -/** - * The default {@link SocketChannelConfig} implementation. - */ -public class DefaultSocketChannelConfig extends DefaultChannelConfig - implements SocketChannelConfig { - - protected final Socket javaSocket; - private volatile boolean allowHalfClosure; - - /** - * Creates a new instance. - */ - public DefaultSocketChannelConfig(SocketChannel channel, Socket javaSocket) { - super(channel); - if (javaSocket == null) { - throw new NullPointerException("javaSocket"); - } - this.javaSocket = javaSocket; - - // Enable TCP_NODELAY by default if possible. - if (PlatformDependent.canEnableTcpNoDelayByDefault()) { - try { - setTcpNoDelay(true); - } catch (Exception e) { - // Ignore. - } - } - } - - @Override - public Map, Object> getOptions() { - return getOptions( - super.getOptions(), - SO_RCVBUF, SO_SNDBUF, TCP_NODELAY, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, IP_TOS, - ALLOW_HALF_CLOSURE); - } - - - @Override - public T getOption(ChannelOption option) { - if (option == SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == SO_SNDBUF) { - return (T) Integer.valueOf(getSendBufferSize()); - } - if (option == TCP_NODELAY) { - return (T) Boolean.valueOf(isTcpNoDelay()); - } - if (option == SO_KEEPALIVE) { - return (T) Boolean.valueOf(isKeepAlive()); - } - if (option == SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == SO_LINGER) { - return (T) Integer.valueOf(getSoLinger()); - } - if (option == IP_TOS) { - return (T) Integer.valueOf(getTrafficClass()); - } - if (option == ALLOW_HALF_CLOSURE) { - return (T) Boolean.valueOf(isAllowHalfClosure()); - } - - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == SO_SNDBUF) { - setSendBufferSize((Integer) value); - } else if (option == TCP_NODELAY) { - setTcpNoDelay((Boolean) value); - } else if (option == SO_KEEPALIVE) { - setKeepAlive((Boolean) value); - } else if (option == SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == SO_LINGER) { - setSoLinger((Integer) value); - } else if (option == IP_TOS) { - setTrafficClass((Integer) value); - } else if (option == ALLOW_HALF_CLOSURE) { - setAllowHalfClosure((Boolean) value); - } else { - return super.setOption(option, value); - } - - return true; - } - - @Override - public int getReceiveBufferSize() { - try { - return javaSocket.getReceiveBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public int getSendBufferSize() { - try { - return javaSocket.getSendBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public int getSoLinger() { - try { - return javaSocket.getSoLinger(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public int getTrafficClass() { - try { - return javaSocket.getTrafficClass(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public boolean isKeepAlive() { - try { - return javaSocket.getKeepAlive(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public boolean isReuseAddress() { - try { - return javaSocket.getReuseAddress(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public boolean isTcpNoDelay() { - try { - return javaSocket.getTcpNoDelay(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public SocketChannelConfig setKeepAlive(boolean keepAlive) { - try { - javaSocket.setKeepAlive(keepAlive); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setPerformancePreferences( - int connectionTime, int latency, int bandwidth) { - javaSocket.setPerformancePreferences(connectionTime, latency, bandwidth); - return this; - } - - @Override - public SocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - try { - javaSocket.setReceiveBufferSize(receiveBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setReuseAddress(boolean reuseAddress) { - try { - javaSocket.setReuseAddress(reuseAddress); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setSendBufferSize(int sendBufferSize) { - try { - javaSocket.setSendBufferSize(sendBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setSoLinger(int soLinger) { - try { - if (soLinger < 0) { - javaSocket.setSoLinger(false, 0); - } else { - javaSocket.setSoLinger(true, soLinger); - } - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) { - try { - javaSocket.setTcpNoDelay(tcpNoDelay); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setTrafficClass(int trafficClass) { - try { - javaSocket.setTrafficClass(trafficClass); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public boolean isAllowHalfClosure() { - return allowHalfClosure; - } - - @Override - public SocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure) { - this.allowHalfClosure = allowHalfClosure; - return this; - } - - @Override - public SocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public SocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public SocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public SocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public SocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public SocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public SocketChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public SocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public SocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public SocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } -} diff --git a/java/src/game/net/channel/socket/ServerSocketChannel.java b/java/src/game/net/channel/socket/ServerSocketChannel.java deleted file mode 100644 index b724782..0000000 --- a/java/src/game/net/channel/socket/ServerSocketChannel.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket; - -import java.net.InetSocketAddress; - -import game.net.channel.ServerChannel; - -/** - * A TCP/IP {@link ServerChannel} which accepts incoming TCP/IP connections. - */ -public interface ServerSocketChannel extends ServerChannel { - @Override - ServerSocketChannelConfig config(); - @Override - InetSocketAddress localAddress(); - @Override - InetSocketAddress remoteAddress(); -} diff --git a/java/src/game/net/channel/socket/ServerSocketChannelConfig.java b/java/src/game/net/channel/socket/ServerSocketChannelConfig.java deleted file mode 100644 index 2017b73..0000000 --- a/java/src/game/net/channel/socket/ServerSocketChannelConfig.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket; - -import game.net.buffer.ByteBufAllocator; -import game.net.channel.ChannelConfig; -import game.net.channel.MessageSizeEstimator; -import game.net.channel.RecvByteBufAllocator; - -/** - * A {@link ChannelConfig} for a {@link ServerSocketChannel}. - * - *

Available options

- * - * In addition to the options provided by {@link ChannelConfig}, - * {@link ServerSocketChannelConfig} allows the following options in the - * option map: - * - * - * - * - * - * - * - * - * - * - * - *
NameAssociated setter method
{@code "backlog"}{@link #setBacklog(int)}
{@code "reuseAddress"}{@link #setReuseAddress(boolean)}
{@code "receiveBufferSize"}{@link #setReceiveBufferSize(int)}
- */ -public interface ServerSocketChannelConfig extends ChannelConfig { - - /** - * Gets the backlog value to specify when the channel binds to a local - * address. - */ - int getBacklog(); - - /** - * Sets the backlog value to specify when the channel binds to a local - * address. - */ - ServerSocketChannelConfig setBacklog(int backlog); - - /** - * Gets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - boolean isReuseAddress(); - - /** - * Sets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - ServerSocketChannelConfig setReuseAddress(boolean reuseAddress); - - /** - * Gets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - int getReceiveBufferSize(); - - /** - * Gets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - ServerSocketChannelConfig setReceiveBufferSize(int receiveBufferSize); - - /** - * Sets the performance preferences as specified in - * {@link ServerSocket#setPerformancePreferences(int, int, int)}. - */ - ServerSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth); - - @Override - ServerSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - ServerSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - ServerSocketChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - ServerSocketChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - ServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - ServerSocketChannelConfig setAutoRead(boolean autoRead); - - @Override - ServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/java/src/game/net/channel/socket/SocketChannel.java b/java/src/game/net/channel/socket/SocketChannel.java deleted file mode 100644 index 5046279..0000000 --- a/java/src/game/net/channel/socket/SocketChannel.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket; - -import java.net.InetSocketAddress; - -import game.net.channel.Channel; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelPromise; - -/** - * A TCP/IP socket {@link Channel}. - */ -public interface SocketChannel extends Channel { - @Override - ServerSocketChannel parent(); - - @Override - SocketChannelConfig config(); - @Override - InetSocketAddress localAddress(); - @Override - InetSocketAddress remoteAddress(); - - /** - * Returns {@code true} if and only if the remote peer shut down its output so that no more - * data is received from this channel. Note that the semantic of this method is different from - * that of {@link Socket#shutdownInput()} and {@link Socket#isInputShutdown()}. - */ - boolean isInputShutdown(); - - /** - * @see Socket#isOutputShutdown() - */ - boolean isOutputShutdown(); - - /** - * @see Socket#shutdownOutput() - */ - ChannelFuture shutdownOutput(); - - /** - * @see Socket#shutdownOutput() - * - * Will notify the given {@link ChannelPromise} - */ - ChannelFuture shutdownOutput(ChannelPromise future); -} diff --git a/java/src/game/net/channel/socket/SocketChannelConfig.java b/java/src/game/net/channel/socket/SocketChannelConfig.java deleted file mode 100644 index 3a3dd1b..0000000 --- a/java/src/game/net/channel/socket/SocketChannelConfig.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket; - -import game.net.buffer.ByteBufAllocator; -import game.net.channel.ChannelConfig; -import game.net.channel.MessageSizeEstimator; -import game.net.channel.RecvByteBufAllocator; - -/** - * A {@link ChannelConfig} for a {@link SocketChannel}. - * - *

Available options

- * - * In addition to the options provided by {@link ChannelConfig}, - * {@link SocketChannelConfig} allows the following options in the option map: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameAssociated setter method
{@link ChannelOption#SO_KEEPALIVE}{@link #setKeepAlive(boolean)}
{@link ChannelOption#SO_REUSEADDR}{@link #setReuseAddress(boolean)}
{@link ChannelOption#SO_LINGER}{@link #setSoLinger(int)}
{@link ChannelOption#TCP_NODELAY}{@link #setTcpNoDelay(boolean)}
{@link ChannelOption#SO_RCVBUF}{@link #setReceiveBufferSize(int)}
{@link ChannelOption#SO_SNDBUF}{@link #setSendBufferSize(int)}
{@link ChannelOption#IP_TOS}{@link #setTrafficClass(int)}
{@link ChannelOption#ALLOW_HALF_CLOSURE}{@link #setAllowHalfClosure(boolean)}
- */ -public interface SocketChannelConfig extends ChannelConfig { - - /** - * Gets the {@link StandardSocketOptions#TCP_NODELAY} option. Please note that the default value of this option - * is {@code true} unlike the operating system default ({@code false}). However, for some buggy platforms, such as - * Android, that shows erratic behavior with Nagle's algorithm disabled, the default value remains to be - * {@code false}. - */ - boolean isTcpNoDelay(); - - /** - * Sets the {@link StandardSocketOptions#TCP_NODELAY} option. Please note that the default value of this option - * is {@code true} unlike the operating system default ({@code false}). However, for some buggy platforms, such as - * Android, that shows erratic behavior with Nagle's algorithm disabled, the default value remains to be - * {@code false}. - */ - SocketChannelConfig setTcpNoDelay(boolean tcpNoDelay); - - /** - * Gets the {@link StandardSocketOptions#SO_LINGER} option. - */ - int getSoLinger(); - - /** - * Sets the {@link StandardSocketOptions#SO_LINGER} option. - */ - SocketChannelConfig setSoLinger(int soLinger); - - /** - * Gets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - int getSendBufferSize(); - - /** - * Sets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - SocketChannelConfig setSendBufferSize(int sendBufferSize); - - /** - * Gets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - int getReceiveBufferSize(); - - /** - * Sets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - SocketChannelConfig setReceiveBufferSize(int receiveBufferSize); - - /** - * Gets the {@link StandardSocketOptions#SO_KEEPALIVE} option. - */ - boolean isKeepAlive(); - - /** - * Sets the {@link StandardSocketOptions#SO_KEEPALIVE} option. - */ - SocketChannelConfig setKeepAlive(boolean keepAlive); - - /** - * Gets the {@link StandardSocketOptions#IP_TOS} option. - */ - int getTrafficClass(); - - /** - * Sets the {@link StandardSocketOptions#IP_TOS} option. - */ - SocketChannelConfig setTrafficClass(int trafficClass); - - /** - * Gets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - boolean isReuseAddress(); - - /** - * Sets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - SocketChannelConfig setReuseAddress(boolean reuseAddress); - - /** - * Sets the performance preferences as specified in - * {@link Socket#setPerformancePreferences(int, int, int)}. - */ - SocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth); - - /** - * Returns {@code true} if and only if the channel should not close itself when its remote - * peer shuts down output to make the connection half-closed. If {@code false}, the connection - * is closed automatically when the remote peer shuts down output. - */ - boolean isAllowHalfClosure(); - - /** - * Sets whether the channel should not close itself when its remote peer shuts down output to - * make the connection half-closed. If {@code true} the connection is not closed when the - * remote peer shuts down output. Instead, - * {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} - * is invoked with a {@link ChannelInputShutdownEvent} object. If {@code false}, the connection - * is closed automatically. - */ - SocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure); - - @Override - SocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - SocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - SocketChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - SocketChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - SocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - SocketChannelConfig setAutoRead(boolean autoRead); - - @Override - SocketChannelConfig setAutoClose(boolean autoClose); - - @Override - SocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/java/src/game/net/channel/socket/nio/NioServerSocketChannel.java b/java/src/game/net/channel/socket/nio/NioServerSocketChannel.java deleted file mode 100644 index 45db772..0000000 --- a/java/src/game/net/channel/socket/nio/NioServerSocketChannel.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket.nio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.SocketAddress; -import java.nio.channels.SelectionKey; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.nio.channels.spi.SelectorProvider; -import java.util.List; - -import game.net.channel.ChannelException; -import game.net.channel.ChannelMetadata; -import game.net.channel.ChannelOutboundBuffer; -import game.net.channel.nio.AbstractNioMessageChannel; -import game.net.channel.socket.DefaultServerSocketChannelConfig; -import game.net.channel.socket.ServerSocketChannelConfig; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A {@link io.netty.channel.socket.ServerSocketChannel} implementation which uses - * NIO selector based implementation to accept new connections. - */ -public class NioServerSocketChannel extends AbstractNioMessageChannel - implements game.net.channel.socket.ServerSocketChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioServerSocketChannel.class); - - private static ServerSocketChannel newSocket(SelectorProvider provider) { - try { - /** - * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in - * {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise. - * - * See #2308. - */ - return provider.openServerSocketChannel(); - } catch (IOException e) { - throw new ChannelException( - "Failed to open a server socket.", e); - } - } - - private final ServerSocketChannelConfig config; - - /** - * Create a new instance - */ - public NioServerSocketChannel() { - this(newSocket(DEFAULT_SELECTOR_PROVIDER)); - } - - /** - * Create a new instance using the given {@link SelectorProvider}. - */ - public NioServerSocketChannel(SelectorProvider provider) { - this(newSocket(provider)); - } - - /** - * Create a new instance using the given {@link ServerSocketChannel}. - */ - public NioServerSocketChannel(ServerSocketChannel channel) { - super(null, channel, SelectionKey.OP_ACCEPT); - config = new NioServerSocketChannelConfig(this, javaChannel().socket()); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public ServerSocketChannelConfig config() { - return config; - } - - @Override - public boolean isActive() { - return javaChannel().socket().isBound(); - } - - @Override - public InetSocketAddress remoteAddress() { - return null; - } - - @Override - protected ServerSocketChannel javaChannel() { - return (ServerSocketChannel) super.javaChannel(); - } - - @Override - protected SocketAddress localAddress0() { - return javaChannel().socket().getLocalSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - javaChannel().socket().bind(localAddress, config.getBacklog()); - } - - @Override - protected void doClose() throws Exception { - javaChannel().close(); - } - - @Override - protected int doReadMessages(List buf) throws Exception { - SocketChannel ch = javaChannel().accept(); - - try { - if (ch != null) { - buf.add(new NioSocketChannel(this, ch)); - return 1; - } - } catch (Throwable t) { - logger.warn("Failed to create a new channel from an accepted socket.", t); - - try { - ch.close(); - } catch (Throwable t2) { - logger.warn("Failed to close a socket.", t2); - } - } - - return 0; - } - - // Unnecessary stuff - @Override - protected boolean doConnect( - SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected void doFinishConnect() throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected SocketAddress remoteAddress0() { - return null; - } - - @Override - protected void doDisconnect() throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected final Object filterOutboundMessage(Object msg) throws Exception { - throw new UnsupportedOperationException(); - } - - private final class NioServerSocketChannelConfig extends DefaultServerSocketChannelConfig { - private NioServerSocketChannelConfig(NioServerSocketChannel channel, ServerSocket javaSocket) { - super(channel, javaSocket); - } - - @Override - protected void autoReadCleared() { - setReadPending(false); - } - } -} diff --git a/java/src/game/net/channel/socket/nio/NioSocketChannel.java b/java/src/game/net/channel/socket/nio/NioSocketChannel.java deleted file mode 100644 index 7092551..0000000 --- a/java/src/game/net/channel/socket/nio/NioSocketChannel.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.channel.socket.nio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.nio.channels.spi.SelectorProvider; - -import game.net.buffer.ByteBuf; -import game.net.channel.Channel; -import game.net.channel.ChannelException; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelMetadata; -import game.net.channel.ChannelOutboundBuffer; -import game.net.channel.ChannelPromise; -import game.net.channel.EventLoop; -import game.net.channel.nio.AbstractNioByteChannel; -import game.net.channel.socket.DefaultSocketChannelConfig; -import game.net.channel.socket.ServerSocketChannel; -import game.net.channel.socket.SocketChannelConfig; -import game.net.util.internal.OneTimeTask; - -/** - * {@link io.netty.channel.socket.SocketChannel} which uses NIO selector based implementation. - */ -public class NioSocketChannel extends AbstractNioByteChannel implements game.net.channel.socket.SocketChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); - - private static SocketChannel newSocket(SelectorProvider provider) { - try { - /** - * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in - * {@link SelectorProvider#provider()} which is called by each SocketChannel.open() otherwise. - * - * See #2308. - */ - return provider.openSocketChannel(); - } catch (IOException e) { - throw new ChannelException("Failed to open a socket.", e); - } - } - - private final SocketChannelConfig config; - - /** - * Create a new instance - */ - public NioSocketChannel() { - this(newSocket(DEFAULT_SELECTOR_PROVIDER)); - } - - /** - * Create a new instance using the given {@link SelectorProvider}. - */ - public NioSocketChannel(SelectorProvider provider) { - this(newSocket(provider)); - } - - /** - * Create a new instance using the given {@link SocketChannel}. - */ - public NioSocketChannel(SocketChannel socket) { - this(null, socket); - } - - /** - * Create a new instance - * - * @param parent the {@link Channel} which created this instance or {@code null} if it was created by the user - * @param socket the {@link SocketChannel} which will be used - */ - public NioSocketChannel(Channel parent, SocketChannel socket) { - super(parent, socket); - config = new NioSocketChannelConfig(this, socket.socket()); - } - - @Override - public ServerSocketChannel parent() { - return (ServerSocketChannel) super.parent(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public SocketChannelConfig config() { - return config; - } - - @Override - protected SocketChannel javaChannel() { - return (SocketChannel) super.javaChannel(); - } - - @Override - public boolean isActive() { - SocketChannel ch = javaChannel(); - return ch.isOpen() && ch.isConnected(); - } - - @Override - public boolean isInputShutdown() { - return super.isInputShutdown(); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - public boolean isOutputShutdown() { - return javaChannel().socket().isOutputShutdown() || !isActive(); - } - - @Override - public ChannelFuture shutdownOutput() { - return shutdownOutput(newPromise()); - } - - @Override - public ChannelFuture shutdownOutput(final ChannelPromise promise) { - EventLoop loop = eventLoop(); - if (loop.inEventLoop()) { - try { - javaChannel().socket().shutdownOutput(); - promise.setSuccess(); - } catch (Throwable t) { - promise.setFailure(t); - } - } else { - loop.execute(new OneTimeTask() { - @Override - public void run() { - shutdownOutput(promise); - } - }); - } - return promise; - } - - @Override - protected SocketAddress localAddress0() { - return javaChannel().socket().getLocalSocketAddress(); - } - - @Override - protected SocketAddress remoteAddress0() { - return javaChannel().socket().getRemoteSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - javaChannel().socket().bind(localAddress); - } - - @Override - protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - if (localAddress != null) { - javaChannel().socket().bind(localAddress); - } - - boolean success = false; - try { - boolean connected = javaChannel().connect(remoteAddress); - if (!connected) { - selectionKey().interestOps(SelectionKey.OP_CONNECT); - } - success = true; - return connected; - } finally { - if (!success) { - doClose(); - } - } - } - - @Override - protected void doFinishConnect() throws Exception { - if (!javaChannel().finishConnect()) { - throw new Error(); - } - } - - @Override - protected void doDisconnect() throws Exception { - doClose(); - } - - @Override - protected void doClose() throws Exception { - javaChannel().close(); - } - - @Override - protected int doReadBytes(ByteBuf byteBuf) throws Exception { - return byteBuf.writeBytes(javaChannel(), byteBuf.writableBytes()); - } - - @Override - protected int doWriteBytes(ByteBuf buf) throws Exception { - final int expectedWrittenBytes = buf.readableBytes(); - return buf.readBytes(javaChannel(), expectedWrittenBytes); - } - -// @Override -// protected long doWriteFileRegion(FileRegion region) throws Exception { -// final long position = region.transfered(); -// return region.transferTo(javaChannel(), position); -// } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - for (;;) { - int size = in.size(); - if (size == 0) { - // All written so clear OP_WRITE - clearOpWrite(); - break; - } - long writtenBytes = 0; - boolean done = false; - boolean setOpWrite = false; - - // Ensure the pending writes are made of ByteBufs only. - ByteBuffer[] nioBuffers = in.nioBuffers(); - int nioBufferCnt = in.nioBufferCount(); - long expectedWrittenBytes = in.nioBufferSize(); - SocketChannel ch = javaChannel(); - - // Always us nioBuffers() to workaround data-corruption. - // See https://github.com/netty/netty/issues/2761 - switch (nioBufferCnt) { - case 0: - // We have something else beside ByteBuffers to write so fallback to normal writes. - super.doWrite(in); - return; - case 1: - // Only one ByteBuf so use non-gathering write - ByteBuffer nioBuffer = nioBuffers[0]; - for (int i = config().getWriteSpinCount() - 1; i >= 0; i --) { - final int localWrittenBytes = ch.write(nioBuffer); - if (localWrittenBytes == 0) { - setOpWrite = true; - break; - } - expectedWrittenBytes -= localWrittenBytes; - writtenBytes += localWrittenBytes; - if (expectedWrittenBytes == 0) { - done = true; - break; - } - } - break; - default: - for (int i = config().getWriteSpinCount() - 1; i >= 0; i --) { - final long localWrittenBytes = ch.write(nioBuffers, 0, nioBufferCnt); - if (localWrittenBytes == 0) { - setOpWrite = true; - break; - } - expectedWrittenBytes -= localWrittenBytes; - writtenBytes += localWrittenBytes; - if (expectedWrittenBytes == 0) { - done = true; - break; - } - } - break; - } - - // Release the fully written buffers, and update the indexes of the partially written buffer. - in.removeBytes(writtenBytes); - - if (!done) { - // Did not write all buffers completely. - incompleteWrite(setOpWrite); - break; - } - } - } - - private final class NioSocketChannelConfig extends DefaultSocketChannelConfig { - private NioSocketChannelConfig(NioSocketChannel channel, Socket javaSocket) { - super(channel, javaSocket); - } - - @Override - protected void autoReadCleared() { - setReadPending(false); - } - } -} diff --git a/java/src/game/net/handler/codec/ByteToMessageDecoder.java b/java/src/game/net/handler/codec/ByteToMessageDecoder.java deleted file mode 100644 index 65e5b28..0000000 --- a/java/src/game/net/handler/codec/ByteToMessageDecoder.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.codec; - -import java.util.List; - -import game.net.buffer.ByteBuf; -import game.net.buffer.Unpooled; -import game.net.channel.ChannelHandlerContext; -import game.net.channel.ChannelInboundHandlerAdapter; -import game.net.util.internal.RecyclableArrayList; -import game.net.util.internal.StringUtil; - -/** - * {@link ChannelInboundHandlerAdapter} which decodes bytes in a stream-like fashion from one {@link ByteBuf} to an - * other Message type. - * - * For example here is an implementation which reads all readable bytes from - * the input {@link ByteBuf} and create a new {@link ByteBuf}. - * - *
- *     public class SquareDecoder extends {@link ByteToMessageDecoder} {
- *         {@code @Override}
- *         public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, List<Object> out)
- *                 throws {@link Exception} {
- *             out.add(in.readBytes(in.readableBytes()));
- *         }
- *     }
- * 
- * - * Be aware that sub-classes of {@link ByteToMessageDecoder} MUST NOT - * annotated with {@link @Sharable}. - */ -public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter { - - ByteBuf cumulation; - private boolean singleDecode; - private boolean decodeWasNull; - private boolean first; - - protected ByteToMessageDecoder() { - if (isSharable()) { - throw new IllegalStateException("@Sharable annotation is not allowed"); - } - } - - /** - * If set then only one message is decoded on each {@link #channelRead(ChannelHandlerContext, Object)} - * call. This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. - * - * Default is {@code false} as this has performance impacts. - */ - public void setSingleDecode(boolean singleDecode) { - this.singleDecode = singleDecode; - } - - /** - * If {@code true} then only one message is decoded on each - * {@link #channelRead(ChannelHandlerContext, Object)} call. - * - * Default is {@code false} as this has performance impacts. - */ - public boolean isSingleDecode() { - return singleDecode; - } - - /** - * Returns the actual number of readable bytes in the internal cumulative - * buffer of this decoder. You usually do not need to rely on this value - * to write a decoder. Use it only when you must use it at your own risk. - * This method is a shortcut to {@link #internalBuffer() internalBuffer().readableBytes()}. - */ - protected int actualReadableBytes() { - return internalBuffer().readableBytes(); - } - - /** - * Returns the internal cumulative buffer of this decoder. You usually - * do not need to access the internal buffer directly to write a decoder. - * Use it only when you must use it at your own risk. - */ - protected ByteBuf internalBuffer() { - if (cumulation != null) { - return cumulation; - } else { - return Unpooled.EMPTY_BUFFER; - } - } - - @Override - public final void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - ByteBuf buf = internalBuffer(); - int readable = buf.readableBytes(); - if (buf.isReadable()) { - ByteBuf bytes = buf.readBytes(readable); - buf.release(); - ctx.fireChannelRead(bytes); - } else { - buf.release(); - } - cumulation = null; - ctx.fireChannelReadComplete(); - handlerRemoved0(ctx); - } - - /** - * Gets called after the {@link ByteToMessageDecoder} was removed from the actual context and it doesn't handle - * events anymore. - */ - protected void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof ByteBuf) { - RecyclableArrayList out = RecyclableArrayList.newInstance(); - try { - ByteBuf data = (ByteBuf) msg; - first = cumulation == null; - if (first) { - cumulation = data; - } else { - if (cumulation.writerIndex() > cumulation.maxCapacity() - data.readableBytes() - || cumulation.refCnt() > 1) { - // Expand cumulation (by replace it) when either there is not more room in the buffer - // or if the refCnt is greater then 1 which may happen when the user use slice().retain() or - // duplicate().retain(). - // - // See: - // - https://github.com/netty/netty/issues/2327 - // - https://github.com/netty/netty/issues/1764 - expandCumulation(ctx, data.readableBytes()); - } - cumulation.writeBytes(data); - data.release(); - } - callDecode(ctx, cumulation, out); - } catch (DecoderException e) { - throw e; - } catch (Throwable t) { - throw new DecoderException(t); - } finally { - if (cumulation != null && !cumulation.isReadable()) { - cumulation.release(); - cumulation = null; - } - int size = out.size(); - decodeWasNull = size == 0; - - for (int i = 0; i < size; i ++) { - ctx.fireChannelRead(out.get(i)); - } - out.recycle(); - } - } else { - ctx.fireChannelRead(msg); - } - } - - private void expandCumulation(ChannelHandlerContext ctx, int readable) { - ByteBuf oldCumulation = cumulation; - cumulation = ctx.alloc().buffer(oldCumulation.readableBytes() + readable); - cumulation.writeBytes(oldCumulation); - oldCumulation.release(); - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - if (cumulation != null && !first && cumulation.refCnt() == 1) { - // discard some bytes if possible to make more room in the - // buffer but only if the refCnt == 1 as otherwise the user may have - // used slice().retain() or duplicate().retain(). - // - // See: - // - https://github.com/netty/netty/issues/2327 - // - https://github.com/netty/netty/issues/1764 - cumulation.discardSomeReadBytes(); - } - if (decodeWasNull) { - decodeWasNull = false; - if (!ctx.channel().config().isAutoRead()) { - ctx.read(); - } - } - ctx.fireChannelReadComplete(); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - RecyclableArrayList out = RecyclableArrayList.newInstance(); - try { - if (cumulation != null) { - callDecode(ctx, cumulation, out); - decodeLast(ctx, cumulation, out); - } else { - decodeLast(ctx, Unpooled.EMPTY_BUFFER, out); - } - } catch (DecoderException e) { - throw e; - } catch (Exception e) { - throw new DecoderException(e); - } finally { - try { - if (cumulation != null) { - cumulation.release(); - cumulation = null; - } - int size = out.size(); - for (int i = 0; i < size; i++) { - ctx.fireChannelRead(out.get(i)); - } - if (size > 0) { - // Something was read, call fireChannelReadComplete() - ctx.fireChannelReadComplete(); - } - ctx.fireChannelInactive(); - } finally { - // recycle in all cases - out.recycle(); - } - } - } - - /** - * Called once data should be decoded from the given {@link ByteBuf}. This method will call - * {@link #decode(ChannelHandlerContext, ByteBuf, List)} as long as decoding should take place. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @param out the {@link List} to which decoded messages should be added - */ - protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List out) { - try { - while (in.isReadable()) { - int outSize = out.size(); - int oldInputLength = in.readableBytes(); - decode(ctx, in, out); - - // Check if this handler was removed before continuing the loop. - // If it was removed, it is not safe to continue to operate on the buffer. - // - // See https://github.com/netty/netty/issues/1664 - if (ctx.isRemoved()) { - break; - } - - if (outSize == out.size()) { - if (oldInputLength == in.readableBytes()) { - break; - } else { - continue; - } - } - - if (oldInputLength == in.readableBytes()) { - throw new DecoderException( - StringUtil.simpleClassName(getClass()) + - ".decode() did not read anything but decoded a message."); - } - - if (isSingleDecode()) { - break; - } - } - } catch (DecoderException e) { - throw e; - } catch (Throwable cause) { - throw new DecoderException(cause); - } - } - - /** - * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input - * {@link ByteBuf} has nothing to read when return from this method or till nothing was read from the input - * {@link ByteBuf}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @param out the {@link List} to which decoded messages should be added - * @throws Exception is thrown if an error accour - */ - protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception; - - /** - * Is called one last time when the {@link ChannelHandlerContext} goes in-active. Which means the - * {@link #channelInactive(ChannelHandlerContext)} was triggered. - * - * By default this will just call {@link #decode(ChannelHandlerContext, ByteBuf, List)} but sub-classes may - * override this for some special cleanup operation. - */ - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - decode(ctx, in, out); - } -} diff --git a/java/src/game/net/handler/codec/CodecException.java b/java/src/game/net/handler/codec/CodecException.java deleted file mode 100644 index 5d59830..0000000 --- a/java/src/game/net/handler/codec/CodecException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.codec; - -/** - * An {@link Exception} which is thrown by a codec. - */ -public class CodecException extends RuntimeException { - - private static final long serialVersionUID = -1464830400709348473L; - - /** - * Creates a new instance. - */ - public CodecException() { - } - - /** - * Creates a new instance. - */ - public CodecException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public CodecException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public CodecException(Throwable cause) { - super(cause); - } -} diff --git a/java/src/game/net/handler/codec/CorruptedFrameException.java b/java/src/game/net/handler/codec/CorruptedFrameException.java deleted file mode 100644 index ecce79c..0000000 --- a/java/src/game/net/handler/codec/CorruptedFrameException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.codec; - -/** - * An {@link DecoderException} which is thrown when the received frame data could not be decoded by - * an inbound handler. - */ -public class CorruptedFrameException extends DecoderException { - - private static final long serialVersionUID = 3918052232492988408L; - - /** - * Creates a new instance. - */ - public CorruptedFrameException() { - } - - /** - * Creates a new instance. - */ - public CorruptedFrameException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public CorruptedFrameException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public CorruptedFrameException(Throwable cause) { - super(cause); - } -} diff --git a/java/src/game/net/handler/codec/DecoderException.java b/java/src/game/net/handler/codec/DecoderException.java deleted file mode 100644 index b6d8c4b..0000000 --- a/java/src/game/net/handler/codec/DecoderException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.codec; - -/** - * An {@link CodecException} which is thrown by a dencoder. - */ -public class DecoderException extends CodecException { - - private static final long serialVersionUID = 6926716840699621852L; - - /** - * Creates a new instance. - */ - public DecoderException() { - } - - /** - * Creates a new instance. - */ - public DecoderException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public DecoderException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public DecoderException(Throwable cause) { - super(cause); - } -} diff --git a/java/src/game/net/handler/codec/EncoderException.java b/java/src/game/net/handler/codec/EncoderException.java deleted file mode 100644 index da8853b..0000000 --- a/java/src/game/net/handler/codec/EncoderException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.codec; - -/** - * An {@link CodecException} which is thrown by an encoder. - */ -public class EncoderException extends CodecException { - - private static final long serialVersionUID = -5086121160476476774L; - - /** - * Creates a new instance. - */ - public EncoderException() { - } - - /** - * Creates a new instance. - */ - public EncoderException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public EncoderException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public EncoderException(Throwable cause) { - super(cause); - } -} diff --git a/java/src/game/net/handler/codec/MessageToByteEncoder.java b/java/src/game/net/handler/codec/MessageToByteEncoder.java deleted file mode 100644 index 6dc4564..0000000 --- a/java/src/game/net/handler/codec/MessageToByteEncoder.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.codec; - -import game.net.buffer.ByteBuf; -import game.net.buffer.Unpooled; -import game.net.channel.ChannelHandlerContext; -import game.net.channel.ChannelOutboundHandlerAdapter; -import game.net.channel.ChannelPromise; -import game.net.util.ReferenceCountUtil; -import game.net.util.internal.TypeParameterMatcher; - - -/** - * {@link ChannelOutboundHandlerAdapter} which encodes message in a stream-like fashion from one message to an - * {@link ByteBuf}. - * - * - * Example implementation which encodes {@link Integer}s to a {@link ByteBuf}. - * - *
- *     public class IntegerEncoder extends {@link MessageToByteEncoder}<{@link Integer}> {
- *         {@code @Override}
- *         public void encode({@link ChannelHandlerContext} ctx, {@link Integer} msg, {@link ByteBuf} out)
- *                 throws {@link Exception} {
- *             out.writeInt(msg);
- *         }
- *     }
- * 
- */ -public abstract class MessageToByteEncoder extends ChannelOutboundHandlerAdapter { - - private final TypeParameterMatcher matcher; - private final boolean preferDirect; - - /** - * @see {@link #MessageToByteEncoder(boolean)} with {@code true} as boolean parameter. - */ - protected MessageToByteEncoder() { - this(true); - } - - /** - * @see {@link #MessageToByteEncoder(Class, boolean)} with {@code true} as boolean value. - */ - protected MessageToByteEncoder(Class outboundMessageType) { - this(outboundMessageType, true); - } - - /** - * Create a new instance which will try to detect the types to match out of the type parameter of the class. - * - * @param preferDirect {@code true} if a direct {@link ByteBuf} should be tried to be used as target for - * the encoded messages. If {@code false} is used it will allocate a heap - * {@link ByteBuf}, which is backed by an byte array. - */ - protected MessageToByteEncoder(boolean preferDirect) { - matcher = TypeParameterMatcher.find(this, MessageToByteEncoder.class, "I"); - this.preferDirect = preferDirect; - } - - /** - * Create a new instance - * - * @param outboundMessageType The tpye of messages to match - * @param preferDirect {@code true} if a direct {@link ByteBuf} should be tried to be used as target for - * the encoded messages. If {@code false} is used it will allocate a heap - * {@link ByteBuf}, which is backed by an byte array. - */ - protected MessageToByteEncoder(Class outboundMessageType, boolean preferDirect) { - matcher = TypeParameterMatcher.get(outboundMessageType); - this.preferDirect = preferDirect; - } - - /** - * Returns {@code true} if the given message should be handled. If {@code false} it will be passed to the next - * {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - */ - public boolean acceptOutboundMessage(Object msg) throws Exception { - return matcher.match(msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - ByteBuf buf = null; - try { - if (acceptOutboundMessage(msg)) { - - I cast = (I) msg; - buf = allocateBuffer(ctx, cast, preferDirect); - try { - encode(ctx, cast, buf); - } finally { - ReferenceCountUtil.release(cast); - } - - if (buf.isReadable()) { - ctx.write(buf, promise); - } else { - buf.release(); - ctx.write(Unpooled.EMPTY_BUFFER, promise); - } - buf = null; - } else { - ctx.write(msg, promise); - } - } catch (EncoderException e) { - throw e; - } catch (Throwable e) { - throw new EncoderException(e); - } finally { - if (buf != null) { - buf.release(); - } - } - } - - /** - * Allocate a {@link ByteBuf} which will be used as argument of {@link #encode(ChannelHandlerContext, I, ByteBuf)}. - * Sub-classes may override this method to returna {@link ByteBuf} with a perfect matching {@code initialCapacity}. - */ - protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, I msg, - boolean preferDirect) throws Exception { - if (preferDirect) { - return ctx.alloc().ioBuffer(); - } else { - return ctx.alloc().heapBuffer(); - } - } - - /** - * Encode a message into a {@link ByteBuf}. This method will be called for each written message that can be handled - * by this encoder. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to - * @param msg the message to encode - * @param out the {@link ByteBuf} into which the encoded message will be written - * @throws Exception is thrown if an error accour - */ - protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception; -} diff --git a/java/src/game/net/handler/timeout/ReadTimeoutException.java b/java/src/game/net/handler/timeout/ReadTimeoutException.java deleted file mode 100644 index 2fecba6..0000000 --- a/java/src/game/net/handler/timeout/ReadTimeoutException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.timeout; - -/** - * A {@link TimeoutException} raised by {@link ReadTimeoutHandler} when no data - * was read within a certain period of time. - */ -public final class ReadTimeoutException extends TimeoutException { - - private static final long serialVersionUID = 169287984113283421L; - - public static final ReadTimeoutException INSTANCE = new ReadTimeoutException(); - - private ReadTimeoutException() { } -} diff --git a/java/src/game/net/handler/timeout/ReadTimeoutHandler.java b/java/src/game/net/handler/timeout/ReadTimeoutHandler.java deleted file mode 100644 index 780c627..0000000 --- a/java/src/game/net/handler/timeout/ReadTimeoutHandler.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.timeout; - -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import game.net.channel.ChannelHandlerContext; -import game.net.channel.ChannelInboundHandlerAdapter; - -/** - * Raises a {@link ReadTimeoutException} when no data was read within a certain - * period of time. - * - *
- * // The connection is closed when there is no inbound traffic
- * // for 30 seconds.
- *
- * public class MyChannelInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("readTimeoutHandler", new {@link ReadTimeoutHandler}(30);
- *         channel.pipeline().addLast("myHandler", new MyHandler());
- *     }
- * }
- *
- * // Handler should handle the {@link ReadTimeoutException}.
- * public class MyHandler extends {@link ChannelDuplexHandler} {
- *     {@code @Override}
- *     public void exceptionCaught({@link ChannelHandlerContext} ctx, {@link Throwable} cause)
- *             throws {@link Exception} {
- *         if (cause instanceof {@link ReadTimeoutException}) {
- *             // do something
- *         } else {
- *             super.exceptionCaught(ctx, cause);
- *         }
- *     }
- * }
- *
- * {@link ServerBootstrap} bootstrap = ...;
- * ...
- * bootstrap.childHandler(new MyChannelInitializer());
- * ...
- * 
- * @see WriteTimeoutHandler - * @see IdleStateHandler - */ -public class ReadTimeoutHandler extends ChannelInboundHandlerAdapter { - private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1); - - private final long timeoutNanos; - - private volatile ScheduledFuture timeout; - private volatile long lastReadTime; - - private volatile int state; // 0 - none, 1 - Initialized, 2 - Destroyed; - - private boolean closed; - - /** - * Creates a new instance. - * - * @param timeoutSeconds - * read timeout in seconds - */ - public ReadTimeoutHandler(int timeoutSeconds) { - this(timeoutSeconds, TimeUnit.SECONDS); - } - - /** - * Creates a new instance. - * - * @param timeout - * read timeout - * @param unit - * the {@link TimeUnit} of {@code timeout} - */ - public ReadTimeoutHandler(long timeout, TimeUnit unit) { - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (timeout <= 0) { - timeoutNanos = 0; - } else { - timeoutNanos = Math.max(unit.toNanos(timeout), MIN_TIMEOUT_NANOS); - } - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - if (ctx.channel().isActive() && ctx.channel().isRegistered()) { - // channelActvie() event has been fired already, which means this.channelActive() will - // not be invoked. We have to initialize here instead. - initialize(ctx); - } else { - // channelActive() event has not been fired yet. this.channelActive() will be invoked - // and initialization will occur there. - } - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - destroy(); - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - // Initialize early if channel is active already. - if (ctx.channel().isActive()) { - initialize(ctx); - } - super.channelRegistered(ctx); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - // This method will be invoked only if this handler was added - // before channelActive() event is fired. If a user adds this handler - // after the channelActive() event, initialize() will be called by beforeAdd(). - initialize(ctx); - super.channelActive(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - destroy(); - super.channelInactive(ctx); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - lastReadTime = System.nanoTime(); - ctx.fireChannelRead(msg); - } - - private void initialize(ChannelHandlerContext ctx) { - // Avoid the case where destroy() is called before scheduling timeouts. - // See: https://github.com/netty/netty/issues/143 - switch (state) { - case 1: - case 2: - return; - } - - state = 1; - - lastReadTime = System.nanoTime(); - if (timeoutNanos > 0) { - timeout = ctx.executor().schedule( - new ReadTimeoutTask(ctx), - timeoutNanos, TimeUnit.NANOSECONDS); - } - } - - private void destroy() { - state = 2; - - if (timeout != null) { - timeout.cancel(false); - timeout = null; - } - } - - /** - * Is called when a read timeout was detected. - */ - protected void readTimedOut(ChannelHandlerContext ctx) throws Exception { - if (!closed) { - ctx.fireExceptionCaught(ReadTimeoutException.INSTANCE); - ctx.close(); - closed = true; - } - } - - private final class ReadTimeoutTask implements Runnable { - - private final ChannelHandlerContext ctx; - - ReadTimeoutTask(ChannelHandlerContext ctx) { - this.ctx = ctx; - } - - @Override - public void run() { - if (!ctx.channel().isOpen()) { - return; - } - - long currentTime = System.nanoTime(); - long nextDelay = timeoutNanos - (currentTime - lastReadTime); - if (nextDelay <= 0) { - // Read timed out - set a new timeout and notify the callback. - timeout = ctx.executor().schedule(this, timeoutNanos, TimeUnit.NANOSECONDS); - try { - readTimedOut(ctx); - } catch (Throwable t) { - ctx.fireExceptionCaught(t); - } - } else { - // Read occurred before the timeout - set a new timeout with shorter delay. - timeout = ctx.executor().schedule(this, nextDelay, TimeUnit.NANOSECONDS); - } - } - } -} diff --git a/java/src/game/net/handler/timeout/TimeoutException.java b/java/src/game/net/handler/timeout/TimeoutException.java deleted file mode 100644 index 6f119a5..0000000 --- a/java/src/game/net/handler/timeout/TimeoutException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.handler.timeout; - -import game.net.channel.ChannelException; - -/** - * A {@link TimeoutException} when no data was either read or written within a - * certain period of time. - */ -public class TimeoutException extends ChannelException { - - private static final long serialVersionUID = 4673641882869672533L; - - TimeoutException() { } - - @Override - public Throwable fillInStackTrace() { - return this; - } -} diff --git a/java/src/game/net/util/Attribute.java b/java/src/game/net/util/Attribute.java deleted file mode 100644 index 667d496..0000000 --- a/java/src/game/net/util/Attribute.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -/** - * An attribute which allows to store a value reference. It may be updated atomically and so is thread-safe. - * - * @param the type of the value it holds. - */ -public interface Attribute { - - /** - * Returns the key of this attribute. - */ - AttributeKey key(); - - /** - * Returns the current value, which may be {@code null} - */ - T get(); - - /** - * Sets the value - */ - void set(T value); - - /** - * Atomically sets to the given value and returns the old value which may be {@code null} if non was set before. - */ - T getAndSet(T value); - - /** - * Atomically sets to the given value if this {@link Attribute} does not contain a value at the moment. - * If it was not possible to set the value as it contains a value it will just return the current value. - */ - T setIfAbsent(T value); - - /** - * Removes this attribute from the {@link AttributeMap} and returns the old value.. Subsequent {@link #get()} - * calls will return @{code null}. - */ - T getAndRemove(); - - /** - * Atomically sets the value to the given updated value if the current value == the expected value. - * If it the set was successful it returns {@code true} otherwise {@code false}. - */ - boolean compareAndSet(T oldValue, T newValue); - - /** - * Removes this attribute from the {@link AttributeMap}. Subsequent {@link #get()} calls will return @{code null}. - */ - void remove(); -} diff --git a/java/src/game/net/util/AttributeKey.java b/java/src/game/net/util/AttributeKey.java deleted file mode 100644 index 8264ad8..0000000 --- a/java/src/game/net/util/AttributeKey.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -import java.util.concurrent.ConcurrentMap; - -import game.net.util.internal.PlatformDependent; - -/** - * Key which can be used to access {@link Attribute} out of the {@link AttributeMap}. Be aware that it is not be - * possible to have multiple keys with the same name. - * - * - * @param the type of the {@link Attribute} which can be accessed via this {@link AttributeKey}. - */ - // 'T' is used only at compile time -public final class AttributeKey extends UniqueName { - - private static final ConcurrentMap names = PlatformDependent.newConcurrentHashMap(); - - /** - * Creates a new {@link AttributeKey} with the specified {@code name}. - */ - - public static AttributeKey valueOf(String name) { - return new AttributeKey(name); - } - - /** - * @deprecated Use {@link #valueOf(String)} instead. - */ - @Deprecated - public AttributeKey(String name) { - super(names, name); - } -} diff --git a/java/src/game/net/util/AttributeMap.java b/java/src/game/net/util/AttributeMap.java deleted file mode 100644 index c7ee984..0000000 --- a/java/src/game/net/util/AttributeMap.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -/** - * Holds {@link Attribute}s which can be accessed via {@link AttributeKey}. - * - * Implementations must be Thread-safe. - */ -public interface AttributeMap { - /** - * Get the {@link Attribute} for the given {@link AttributeKey}. This method will never return null, but may return - * an {@link Attribute} which does not have a value set yet. - */ - Attribute attr(AttributeKey key); -} diff --git a/java/src/game/net/util/CharsetUtil.java b/java/src/game/net/util/CharsetUtil.java deleted file mode 100644 index e43b681..0000000 --- a/java/src/game/net/util/CharsetUtil.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CodingErrorAction; -import java.util.Map; - -import game.net.util.internal.InternalThreadLocalMap; - -/** - * A utility class that provides various common operations and constants - * related with {@link Charset} and its relevant classes. - */ -public final class CharsetUtil { - - /** - * 16-bit UTF (UCS Transformation Format) whose byte order is identified by - * an optional byte-order mark - */ - public static final Charset UTF_16 = Charset.forName("UTF-16"); - - /** - * 16-bit UTF (UCS Transformation Format) whose byte order is big-endian - */ - public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); - - /** - * 16-bit UTF (UCS Transformation Format) whose byte order is little-endian - */ - public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); - - /** - * 8-bit UTF (UCS Transformation Format) - */ - public static final Charset UTF_8 = Charset.forName("UTF-8"); - - /** - * ISO Latin Alphabet No. 1, as known as ISO-LATIN-1 - */ - public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - - /** - * 7-bit ASCII, as known as ISO646-US or the Basic Latin block of the - * Unicode character set - */ - public static final Charset US_ASCII = Charset.forName("US-ASCII"); - - /** - * Returns a cached thread-local {@link CharsetEncoder} for the specified - * charset. - */ - public static CharsetEncoder getEncoder(Charset charset) { - if (charset == null) { - throw new NullPointerException("charset"); - } - - Map map = InternalThreadLocalMap.get().charsetEncoderCache(); - CharsetEncoder e = map.get(charset); - if (e != null) { - e.reset(); - e.onMalformedInput(CodingErrorAction.REPLACE); - e.onUnmappableCharacter(CodingErrorAction.REPLACE); - return e; - } - - e = charset.newEncoder(); - e.onMalformedInput(CodingErrorAction.REPLACE); - e.onUnmappableCharacter(CodingErrorAction.REPLACE); - map.put(charset, e); - return e; - } - - /** - * Returns a cached thread-local {@link CharsetDecoder} for the specified - * charset. - */ - public static CharsetDecoder getDecoder(Charset charset) { - if (charset == null) { - throw new NullPointerException("charset"); - } - - Map map = InternalThreadLocalMap.get().charsetDecoderCache(); - CharsetDecoder d = map.get(charset); - if (d != null) { - d.reset(); - d.onMalformedInput(CodingErrorAction.REPLACE); - d.onUnmappableCharacter(CodingErrorAction.REPLACE); - return d; - } - - d = charset.newDecoder(); - d.onMalformedInput(CodingErrorAction.REPLACE); - d.onUnmappableCharacter(CodingErrorAction.REPLACE); - map.put(charset, d); - return d; - } - - private CharsetUtil() { - // Unused - } -} diff --git a/java/src/game/net/util/DefaultAttributeMap.java b/java/src/game/net/util/DefaultAttributeMap.java deleted file mode 100644 index 762c665..0000000 --- a/java/src/game/net/util/DefaultAttributeMap.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicReferenceArray; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -import game.net.util.internal.PlatformDependent; - -/** - * Default {@link AttributeMap} implementation which use simple synchronization per bucket to keep the memory overhead - * as low as possible. - */ -public class DefaultAttributeMap implements AttributeMap { - - - private static final AtomicReferenceFieldUpdater updater; - - static { - - AtomicReferenceFieldUpdater referenceFieldUpdater = - PlatformDependent.newAtomicReferenceFieldUpdater(DefaultAttributeMap.class, "attributes"); - if (referenceFieldUpdater == null) { - referenceFieldUpdater = AtomicReferenceFieldUpdater - .newUpdater(DefaultAttributeMap.class, AtomicReferenceArray.class, "attributes"); - } - updater = referenceFieldUpdater; - } - - private static final int BUCKET_SIZE = 4; - private static final int MASK = BUCKET_SIZE - 1; - - // Initialize lazily to reduce memory consumption; updated by AtomicReferenceFieldUpdater above. - - private volatile AtomicReferenceArray> attributes; - - - @Override - public Attribute attr(AttributeKey key) { - if (key == null) { - throw new NullPointerException("key"); - } - AtomicReferenceArray> attributes = this.attributes; - if (attributes == null) { - // Not using ConcurrentHashMap due to high memory consumption. - attributes = new AtomicReferenceArray>(BUCKET_SIZE); - - if (!updater.compareAndSet(this, null, attributes)) { - attributes = this.attributes; - } - } - - int i = index(key); - DefaultAttribute head = attributes.get(i); - if (head == null) { - // No head exists yet which means we may be able to add the attribute without synchronization and just - // use compare and set. At worst we need to fallback to synchronization - head = new DefaultAttribute(key); - if (attributes.compareAndSet(i, null, head)) { - // we were able to add it so return the head right away - return (Attribute) head; - } else { - head = attributes.get(i); - } - } - - synchronized (head) { - DefaultAttribute curr = head; - for (;;) { - if (!curr.removed && curr.key == key) { - return (Attribute) curr; - } - - DefaultAttribute next = curr.next; - if (next == null) { - DefaultAttribute attr = new DefaultAttribute(head, key); - curr.next = attr; - attr.prev = curr; - return attr; - } else { - curr = next; - } - } - } - } - - private static int index(AttributeKey key) { - return key.id() & MASK; - } - - - private static final class DefaultAttribute extends AtomicReference implements Attribute { - - private static final long serialVersionUID = -2661411462200283011L; - - // The head of the linked-list this attribute belongs to, which may be itself - private final DefaultAttribute head; - private final AttributeKey key; - - // Double-linked list to prev and next node to allow fast removal - private DefaultAttribute prev; - private DefaultAttribute next; - - // Will be set to true one the attribute is removed via getAndRemove() or remove() - private volatile boolean removed; - - DefaultAttribute(DefaultAttribute head, AttributeKey key) { - this.head = head; - this.key = key; - } - - DefaultAttribute(AttributeKey key) { - head = this; - this.key = key; - } - - @Override - public AttributeKey key() { - return key; - } - - @Override - public T setIfAbsent(T value) { - while (!compareAndSet(null, value)) { - T old = get(); - if (old != null) { - return old; - } - } - return null; - } - - @Override - public T getAndRemove() { - removed = true; - T oldValue = getAndSet(null); - remove0(); - return oldValue; - } - - @Override - public void remove() { - removed = true; - set(null); - remove0(); - } - - private void remove0() { - synchronized (head) { - // We only update the linked-list structure if prev != null because if it is null this - // DefaultAttribute acts also as head. The head must never be removed completely and just be - // marked as removed as all synchronization is done on the head itself for each bucket. - // The head itself will be GC'ed once the DefaultAttributeMap is GC'ed. So at most 5 heads will - // be removed lazy as the array size is 5. - if (prev != null) { - prev.next = next; - - if (next != null) { - next.prev = prev; - } - } - } - } - } -} diff --git a/java/src/game/net/util/IllegalReferenceCountException.java b/java/src/game/net/util/IllegalReferenceCountException.java deleted file mode 100644 index 8bb31ae..0000000 --- a/java/src/game/net/util/IllegalReferenceCountException.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util; - -/** - * An {@link IllegalStateException} which is raised when a user attempts to access a {@link ReferenceCounted} whose - * reference count has been decreased to 0 (and consequently freed). - */ -public class IllegalReferenceCountException extends IllegalStateException { - - private static final long serialVersionUID = -2507492394288153468L; - - public IllegalReferenceCountException() { } - - public IllegalReferenceCountException(int refCnt) { - this("refCnt: " + refCnt); - } - - public IllegalReferenceCountException(int refCnt, int increment) { - this("refCnt: " + refCnt + ", " + (increment > 0? "increment: " + increment : "decrement: " + -increment)); - } - - public IllegalReferenceCountException(String message) { - super(message); - } - - public IllegalReferenceCountException(String message, Throwable cause) { - super(message, cause); - } - - public IllegalReferenceCountException(Throwable cause) { - super(cause); - } -} diff --git a/java/src/game/net/util/NetUtil.java b/java/src/game/net/util/NetUtil.java deleted file mode 100644 index 0e15990..0000000 --- a/java/src/game/net/util/NetUtil.java +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.StringTokenizer; - -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A class that holds a number of network-related constants. - *

- * This class borrowed some of its methods from a modified fork of the - * Inet6Util class which was part of Apache Harmony. - */ -public final class NetUtil { - - /** - * The {@link Inet4Address} that represents the IPv4 loopback address '127.0.0.1' - */ - public static final Inet4Address LOCALHOST4; - - /** - * The {@link Inet6Address} that represents the IPv6 loopback address '::1' - */ - public static final Inet6Address LOCALHOST6; - - /** - * The {@link InetAddress} that represents the loopback address. If IPv6 stack is available, it will refer to - * {@link #LOCALHOST6}. Otherwise, {@link #LOCALHOST4}. - */ - public static final InetAddress LOCALHOST; - - /** - * The loopback {@link NetworkInterface} of the current machine - */ - public static final NetworkInterface LOOPBACK_IF; - - /** - * The SOMAXCONN value of the current machine. If failed to get the value, 3072 is used as a - * default value. - */ - public static final int SOMAXCONN; - - /** - * The logger being used by this class - */ - private static final InternalLogger logger = InternalLoggerFactory.getInstance(NetUtil.class); - - static { - byte[] LOCALHOST4_BYTES = {127, 0, 0, 1}; - byte[] LOCALHOST6_BYTES = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - - // Create IPv4 loopback address. - Inet4Address localhost4 = null; - try { - localhost4 = (Inet4Address) InetAddress.getByAddress(LOCALHOST4_BYTES); - } catch (Exception e) { - // We should not get here as long as the length of the address is correct. - PlatformDependent.throwException(e); - } - LOCALHOST4 = localhost4; - - // Create IPv6 loopback address. - Inet6Address localhost6 = null; - try { - localhost6 = (Inet6Address) InetAddress.getByAddress(LOCALHOST6_BYTES); - } catch (Exception e) { - // We should not get here as long as the length of the address is correct. - PlatformDependent.throwException(e); - } - LOCALHOST6 = localhost6; - - // Retrieve the list of available network interfaces. - List ifaces = new ArrayList(); - try { - for (Enumeration i = NetworkInterface.getNetworkInterfaces(); i.hasMoreElements();) { - NetworkInterface iface = i.nextElement(); - // Use the interface with proper INET addresses only. - if (iface.getInetAddresses().hasMoreElements()) { - ifaces.add(iface); - } - } - } catch (SocketException e) { - logger.warn("Failed to retrieve the list of available network interfaces", e); - } - - // Find the first loopback interface available from its INET address (127.0.0.1 or ::1) - // Note that we do not use NetworkInterface.isLoopback() in the first place because it takes long time - // on a certain environment. (e.g. Windows with -Djava.net.preferIPv4Stack=true) - NetworkInterface loopbackIface = null; - InetAddress loopbackAddr = null; - loop: for (NetworkInterface iface: ifaces) { - for (Enumeration i = iface.getInetAddresses(); i.hasMoreElements();) { - InetAddress addr = i.nextElement(); - if (addr.isLoopbackAddress()) { - // Found - loopbackIface = iface; - loopbackAddr = addr; - break loop; - } - } - } - - // If failed to find the loopback interface from its INET address, fall back to isLoopback(). - if (loopbackIface == null) { - try { - for (NetworkInterface iface: ifaces) { - if (iface.isLoopback()) { - Enumeration i = iface.getInetAddresses(); - if (i.hasMoreElements()) { - // Found the one with INET address. - loopbackIface = iface; - loopbackAddr = i.nextElement(); - break; - } - } - } - - if (loopbackIface == null) { - logger.warn("Failed to find the loopback interface"); - } - } catch (SocketException e) { - logger.warn("Failed to find the loopback interface", e); - } - } - - if (loopbackIface != null) { - // Found the loopback interface with an INET address. - logger.debug( - "Loopback interface: {} ({}, {})", - loopbackIface.getName(), loopbackIface.getDisplayName(), loopbackAddr.getHostAddress()); - } else { - // Could not find the loopback interface, but we can't leave LOCALHOST as null. - // Use LOCALHOST6 or LOCALHOST4, preferably the IPv6 one. - if (loopbackAddr == null) { - try { - if (NetworkInterface.getByInetAddress(LOCALHOST6) != null) { - logger.debug("Using hard-coded IPv6 localhost address: {}", localhost6); - loopbackAddr = localhost6; - } - } catch (Exception e) { - // Ignore - } finally { - if (loopbackAddr == null) { - logger.debug("Using hard-coded IPv4 localhost address: {}", localhost4); - loopbackAddr = localhost4; - } - } - } - } - - LOOPBACK_IF = loopbackIface; - LOCALHOST = loopbackAddr; - - // Determine the default somaxconn (server socket backlog) value of the platform. - // The known defaults: - // - Windows NT Server 4.0+: 200 - // - Linux and Mac OS X: 128 - int somaxconn = PlatformDependent.isWindows() ? 200 : 128; - File file = new File("/proc/sys/net/core/somaxconn"); - if (file.exists()) { - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(file)); - somaxconn = Integer.parseInt(in.readLine()); - if (logger.isDebugEnabled()) { - logger.debug("{}: {}", file, somaxconn); - } - } catch (Exception e) { - logger.debug("Failed to get SOMAXCONN from: {}", file, e); - } finally { - if (in != null) { - try { - in.close(); - } catch (Exception e) { - // Ignored. - } - } - } - } else { - if (logger.isDebugEnabled()) { - logger.debug("{}: {} (non-existent)", file, somaxconn); - } - } - - SOMAXCONN = somaxconn; - } - - /** - * Creates an byte[] based on an ipAddressString. No error handling is - * performed here. - */ - public static byte[] createByteArrayFromIpAddressString(String ipAddressString) { - - if (isValidIpV4Address(ipAddressString)) { - StringTokenizer tokenizer = new StringTokenizer(ipAddressString, "."); - String token; - int tempInt; - byte[] byteAddress = new byte[4]; - for (int i = 0; i < 4; i ++) { - token = tokenizer.nextToken(); - tempInt = Integer.parseInt(token); - byteAddress[i] = (byte) tempInt; - } - - return byteAddress; - } - - if (isValidIpV6Address(ipAddressString)) { - if (ipAddressString.charAt(0) == '[') { - ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1); - } - - StringTokenizer tokenizer = new StringTokenizer(ipAddressString, ":.", true); - ArrayList hexStrings = new ArrayList(); - ArrayList decStrings = new ArrayList(); - String token = ""; - String prevToken = ""; - int doubleColonIndex = -1; // If a double colon exists, we need to - // insert 0s. - - // Go through the tokens, including the seperators ':' and '.' - // When we hit a : or . the previous token will be added to either - // the hex list or decimal list. In the case where we hit a :: - // we will save the index of the hexStrings so we can add zeros - // in to fill out the string - while (tokenizer.hasMoreTokens()) { - prevToken = token; - token = tokenizer.nextToken(); - - if (":".equals(token)) { - if (":".equals(prevToken)) { - doubleColonIndex = hexStrings.size(); - } else if (!prevToken.isEmpty()) { - hexStrings.add(prevToken); - } - } else if (".".equals(token)) { - decStrings.add(prevToken); - } - } - - if (":".equals(prevToken)) { - if (":".equals(token)) { - doubleColonIndex = hexStrings.size(); - } else { - hexStrings.add(token); - } - } else if (".".equals(prevToken)) { - decStrings.add(token); - } - - // figure out how many hexStrings we should have - // also check if it is a IPv4 address - int hexStringsLength = 8; - - // If we have an IPv4 address tagged on at the end, subtract - // 4 bytes, or 2 hex words from the total - if (!decStrings.isEmpty()) { - hexStringsLength -= 2; - } - - // if we hit a double Colon add the appropriate hex strings - if (doubleColonIndex != -1) { - int numberToInsert = hexStringsLength - hexStrings.size(); - for (int i = 0; i < numberToInsert; i ++) { - hexStrings.add(doubleColonIndex, "0"); - } - } - - byte[] ipByteArray = new byte[16]; - - // Finally convert these strings to bytes... - for (int i = 0; i < hexStrings.size(); i ++) { - convertToBytes(hexStrings.get(i), ipByteArray, i * 2); - } - - // Now if there are any decimal values, we know where they go... - for (int i = 0; i < decStrings.size(); i ++) { - ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings.get(i)) & 255); - } - return ipByteArray; - } - return null; - } - - /** - * Converts a 4 character hex word into a 2 byte word equivalent - */ - private static void convertToBytes(String hexWord, byte[] ipByteArray, int byteIndex) { - - int hexWordLength = hexWord.length(); - int hexWordIndex = 0; - ipByteArray[byteIndex] = 0; - ipByteArray[byteIndex + 1] = 0; - int charValue; - - // high order 4 bits of first byte - if (hexWordLength > 3) { - charValue = getIntValue(hexWord.charAt(hexWordIndex ++)); - ipByteArray[byteIndex] |= charValue << 4; - } - - // low order 4 bits of the first byte - if (hexWordLength > 2) { - charValue = getIntValue(hexWord.charAt(hexWordIndex ++)); - ipByteArray[byteIndex] |= charValue; - } - - // high order 4 bits of second byte - if (hexWordLength > 1) { - charValue = getIntValue(hexWord.charAt(hexWordIndex ++)); - ipByteArray[byteIndex + 1] |= charValue << 4; - } - - // low order 4 bits of the first byte - charValue = getIntValue(hexWord.charAt(hexWordIndex)); - ipByteArray[byteIndex + 1] |= charValue & 15; - } - - static int getIntValue(char c) { - - switch (c) { - case '0': - return 0; - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - } - - c = Character.toLowerCase(c); - switch (c) { - case 'a': - return 10; - case 'b': - return 11; - case 'c': - return 12; - case 'd': - return 13; - case 'e': - return 14; - case 'f': - return 15; - } - return 0; - } - - public static boolean isValidIpV6Address(String ipAddress) { - int length = ipAddress.length(); - boolean doubleColon = false; - int numberOfColons = 0; - int numberOfPeriods = 0; - int numberOfPercent = 0; - StringBuilder word = new StringBuilder(); - char c = 0; - char prevChar; - int offset = 0; // offset for [] ip addresses - - if (length < 2) { - return false; - } - - for (int i = 0; i < length; i ++) { - prevChar = c; - c = ipAddress.charAt(i); - switch (c) { - - // case for an open bracket [x:x:x:...x] - case '[': - if (i != 0) { - return false; // must be first character - } - if (ipAddress.charAt(length - 1) != ']') { - return false; // must have a close ] - } - offset = 1; - if (length < 4) { - return false; - } - break; - - // case for a closed bracket at end of IP [x:x:x:...x] - case ']': - if (i != length - 1) { - return false; // must be last charcter - } - if (ipAddress.charAt(0) != '[') { - return false; // must have a open [ - } - break; - - // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d - case '.': - numberOfPeriods ++; - if (numberOfPeriods > 3) { - return false; - } - if (!isValidIp4Word(word.toString())) { - return false; - } - if (numberOfColons != 6 && !doubleColon) { - return false; - } - // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an - // IPv4 ending, otherwise 7 :'s is bad - if (numberOfColons == 7 && ipAddress.charAt(offset) != ':' && - ipAddress.charAt(1 + offset) != ':') { - return false; - } - word.delete(0, word.length()); - break; - - case ':': - // FIX "IP6 mechanism syntax #ip6-bad1" - // An IPV6 address cannot start with a single ":". - // Either it can starti with "::" or with a number. - if (i == offset && (ipAddress.length() <= i || ipAddress.charAt(i + 1) != ':')) { - return false; - } - // END FIX "IP6 mechanism syntax #ip6-bad1" - numberOfColons ++; - if (numberOfColons > 7) { - return false; - } - if (numberOfPeriods > 0) { - return false; - } - if (prevChar == ':') { - if (doubleColon) { - return false; - } - doubleColon = true; - } - word.delete(0, word.length()); - break; - case '%': - if (numberOfColons == 0) { - return false; - } - numberOfPercent ++; - - // validate that the stuff after the % is valid - if (i + 1 >= length) { - // in this case the percent is there but no number is - // available - return false; - } - try { - if (Integer.parseInt(ipAddress.substring(i + 1)) < 0) { - return false; - } - } catch (NumberFormatException e) { - // right now we just support an integer after the % so if - // this is not - // what is there then return - return false; - } - break; - - default: - if (numberOfPercent == 0) { - if (word != null && word.length() > 3) { - return false; - } - if (!isValidHexChar(c)) { - return false; - } - } - word.append(c); - } - } - - // Check if we have an IPv4 ending - if (numberOfPeriods > 0) { - // There is a test case with 7 colons and valid ipv4 this should resolve it - if (numberOfPeriods != 3 || !(isValidIp4Word(word.toString()) && numberOfColons < 7)) { - return false; - } - } else { - // If we're at then end and we haven't had 7 colons then there is a - // problem unless we encountered a doubleColon - if (numberOfColons != 7 && !doubleColon) { - return false; - } - - // If we have an empty word at the end, it means we ended in either - // a : or a . - // If we did not end in :: then this is invalid - if (numberOfPercent == 0) { - if (word.length() == 0 && ipAddress.charAt(length - 1 - offset) == ':' && - ipAddress.charAt(length - 2 - offset) != ':') { - return false; - } - } - } - - return true; - } - - public static boolean isValidIp4Word(String word) { - char c; - if (word.length() < 1 || word.length() > 3) { - return false; - } - for (int i = 0; i < word.length(); i ++) { - c = word.charAt(i); - if (!(c >= '0' && c <= '9')) { - return false; - } - } - return Integer.parseInt(word) <= 255; - } - - static boolean isValidHexChar(char c) { - return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'; - } - - /** - * Takes a string and parses it to see if it is a valid IPV4 address. - * - * @return true, if the string represents an IPV4 address in dotted - * notation, false otherwise - */ - public static boolean isValidIpV4Address(String value) { - - int periods = 0; - int i; - int length = value.length(); - - if (length > 15) { - return false; - } - char c; - StringBuilder word = new StringBuilder(); - for (i = 0; i < length; i ++) { - c = value.charAt(i); - if (c == '.') { - periods ++; - if (periods > 3) { - return false; - } - if (word.length() == 0) { - return false; - } - if (Integer.parseInt(word.toString()) > 255) { - return false; - } - word.delete(0, word.length()); - } else if (!Character.isDigit(c)) { - return false; - } else { - if (word.length() > 2) { - return false; - } - word.append(c); - } - } - - if (word.length() == 0 || Integer.parseInt(word.toString()) > 255) { - return false; - } - - return periods == 3; - } - - /** - * A constructor to stop this class being constructed. - */ - private NetUtil() { - // Unused - } -} diff --git a/java/src/game/net/util/Recycler.java b/java/src/game/net/util/Recycler.java deleted file mode 100644 index 249c94b..0000000 --- a/java/src/game/net/util/Recycler.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util; - -import java.lang.ref.WeakReference; -import java.util.Arrays; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import game.net.util.concurrent.FastThreadLocal; -import game.net.util.internal.SystemPropertyUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Light-weight object pool based on a thread-local stack. - * - * @param the type of the pooled object - */ -public abstract class Recycler { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(Recycler.class); - - private static final AtomicInteger ID_GENERATOR = new AtomicInteger(Integer.MIN_VALUE); - private static final int OWN_THREAD_ID = ID_GENERATOR.getAndIncrement(); - private static final int DEFAULT_MAX_CAPACITY; - private static final int INITIAL_CAPACITY; - - static { - // In the future, we might have different maxCapacity for different object types. - // e.g. io.netty.recycler.maxCapacity.writeTask - // io.netty.recycler.maxCapacity.outboundBuffer - int maxCapacity = SystemPropertyUtil.getInt("io.netty.recycler.maxCapacity.default", 0); - if (maxCapacity <= 0) { - // TODO: Some arbitrary large number - should adjust as we get more production experience. - maxCapacity = 262144; - } - - DEFAULT_MAX_CAPACITY = maxCapacity; - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.recycler.maxCapacity.default: {}", DEFAULT_MAX_CAPACITY); - } - - INITIAL_CAPACITY = Math.min(DEFAULT_MAX_CAPACITY, 256); - } - - private final int maxCapacity; - private final FastThreadLocal> threadLocal = new FastThreadLocal>() { - @Override - protected Stack initialValue() { - return new Stack(Recycler.this, Thread.currentThread(), maxCapacity); - } - }; - - protected Recycler() { - this(DEFAULT_MAX_CAPACITY); - } - - protected Recycler(int maxCapacity) { - this.maxCapacity = Math.max(0, maxCapacity); - } - - - public final T get() { - Stack stack = threadLocal.get(); - DefaultHandle handle = stack.pop(); - if (handle == null) { - handle = stack.newHandle(); - handle.value = newObject(handle); - } - return (T) handle.value; - } - - public final boolean recycle(T o, Handle handle) { - DefaultHandle h = (DefaultHandle) handle; - if (h.stack.parent != this) { - return false; - } - if (o != h.value) { - throw new IllegalArgumentException("o does not belong to handle"); - } - h.recycle(); - return true; - } - - protected abstract T newObject(Handle handle); - - public interface Handle { } - - static final class DefaultHandle implements Handle { - private int lastRecycledId; - private int recycleId; - - private Stack stack; - private Object value; - - DefaultHandle(Stack stack) { - this.stack = stack; - } - - public void recycle() { - Thread thread = Thread.currentThread(); - if (thread == stack.thread) { - stack.push(this); - return; - } - // we don't want to have a ref to the queue as the value in our weak map - // so we null it out; to ensure there are no races with restoring it later - // we impose a memory ordering here (no-op on x86) - Map, WeakOrderQueue> delayedRecycled = DELAYED_RECYCLED.get(); - WeakOrderQueue queue = delayedRecycled.get(stack); - if (queue == null) { - delayedRecycled.put(stack, queue = new WeakOrderQueue(stack, thread)); - } - queue.add(this); - } - } - - private static final FastThreadLocal, WeakOrderQueue>> DELAYED_RECYCLED = - new FastThreadLocal, WeakOrderQueue>>() { - @Override - protected Map, WeakOrderQueue> initialValue() { - return new WeakHashMap, WeakOrderQueue>(); - } - }; - - // a queue that makes only moderate guarantees about visibility: items are seen in the correct order, - // but we aren't absolutely guaranteed to ever see anything at all, thereby keeping the queue cheap to maintain - private static final class WeakOrderQueue { - private static final int LINK_CAPACITY = 16; - - // Let Link extend AtomicInteger for intrinsics. The Link itself will be used as writerIndex. - - private static final class Link extends AtomicInteger { - private final DefaultHandle[] elements = new DefaultHandle[LINK_CAPACITY]; - - private int readIndex; - private Link next; - } - - // chain of data items - private Link head, tail; - // pointer to another queue of delayed items for the same stack - private WeakOrderQueue next; - private final WeakReference owner; - private final int id = ID_GENERATOR.getAndIncrement(); - - WeakOrderQueue(Stack stack, Thread thread) { - head = tail = new Link(); - owner = new WeakReference(thread); - synchronized (stack) { - next = stack.head; - stack.head = this; - } - } - - void add(DefaultHandle handle) { - handle.lastRecycledId = id; - - Link tail = this.tail; - int writeIndex; - if ((writeIndex = tail.get()) == LINK_CAPACITY) { - this.tail = tail = tail.next = new Link(); - writeIndex = tail.get(); - } - tail.elements[writeIndex] = handle; - handle.stack = null; - // we lazy set to ensure that setting stack to null appears before we unnull it in the owning thread; - // this also means we guarantee visibility of an element in the queue if we see the index updated - tail.lazySet(writeIndex + 1); - } - - boolean hasFinalData() { - return tail.readIndex != tail.get(); - } - - // transfer as many items as we can from this queue to the stack, returning true if any were transferred - - boolean transfer(Stack to) { - - Link head = this.head; - if (head == null) { - return false; - } - - if (head.readIndex == LINK_CAPACITY) { - if (head.next == null) { - return false; - } - this.head = head = head.next; - } - - int start = head.readIndex; - int end = head.get(); - if (start == end) { - return false; - } - - int count = end - start; - if (to.size + count > to.elements.length) { - to.elements = Arrays.copyOf(to.elements, (to.size + count) * 2); - } - - DefaultHandle[] src = head.elements; - DefaultHandle[] trg = to.elements; - int size = to.size; - while (start < end) { - DefaultHandle element = src[start]; - if (element.recycleId == 0) { - element.recycleId = element.lastRecycledId; - } else if (element.recycleId != element.lastRecycledId) { - throw new IllegalStateException("recycled already"); - } - element.stack = to; - trg[size++] = element; - src[start++] = null; - } - to.size = size; - - if (end == LINK_CAPACITY && head.next != null) { - this.head = head.next; - } - - head.readIndex = end; - return true; - } - } - - static final class Stack { - - // we keep a queue of per-thread queues, which is appended to once only, each time a new thread other - // than the stack owner recycles: when we run out of items in our stack we iterate this collection - // to scavenge those that can be reused. this permits us to incur minimal thread synchronisation whilst - // still recycling all items. - final Recycler parent; - final Thread thread; - private DefaultHandle[] elements; - private final int maxCapacity; - private int size; - - private volatile WeakOrderQueue head; - private WeakOrderQueue cursor, prev; - - Stack(Recycler parent, Thread thread, int maxCapacity) { - this.parent = parent; - this.thread = thread; - this.maxCapacity = maxCapacity; - elements = new DefaultHandle[INITIAL_CAPACITY]; - } - - DefaultHandle pop() { - int size = this.size; - if (size == 0) { - if (!scavenge()) { - return null; - } - size = this.size; - } - size --; - DefaultHandle ret = elements[size]; - if (ret.lastRecycledId != ret.recycleId) { - throw new IllegalStateException("recycled multiple times"); - } - ret.recycleId = 0; - ret.lastRecycledId = 0; - this.size = size; - return ret; - } - - boolean scavenge() { - // continue an existing scavenge, if any - if (scavengeSome()) { - return true; - } - - // reset our scavenge cursor - prev = null; - cursor = head; - return false; - } - - boolean scavengeSome() { - boolean success = false; - WeakOrderQueue cursor = this.cursor, prev = this.prev; - while (cursor != null) { - if (cursor.transfer(this)) { - success = true; - break; - } - WeakOrderQueue next = cursor.next; - if (cursor.owner.get() == null) { - // if the thread associated with the queue is gone, unlink it, after - // performing a volatile read to confirm there is no data left to collect - // we never unlink the first queue, as we don't want to synchronize on updating the head - if (cursor.hasFinalData()) { - for (;;) { - if (!cursor.transfer(this)) { - break; - } - } - } - if (prev != null) { - prev.next = next; - } - } else { - prev = cursor; - } - cursor = next; - } - this.prev = prev; - this.cursor = cursor; - return success; - } - - void push(DefaultHandle item) { - if ((item.recycleId | item.lastRecycledId) != 0) { - throw new IllegalStateException("recycled already"); - } - item.recycleId = item.lastRecycledId = OWN_THREAD_ID; - - int size = this.size; - if (size == elements.length) { - if (size == maxCapacity) { - // Hit the maximum capacity - drop the possibly youngest object. - return; - } - elements = Arrays.copyOf(elements, size << 1); - } - - elements[size] = item; - this.size = size + 1; - } - - DefaultHandle newHandle() { - return new DefaultHandle(this); - } - } -} diff --git a/java/src/game/net/util/ReferenceCountUtil.java b/java/src/game/net/util/ReferenceCountUtil.java deleted file mode 100644 index 1808542..0000000 --- a/java/src/game/net/util/ReferenceCountUtil.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -import game.net.util.internal.StringUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Collection of method to handle objects that may implement {@link ReferenceCounted}. - */ -public final class ReferenceCountUtil { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountUtil.class); - - /** - * Try to call {@link ReferenceCounted#retain()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - - public static T retain(T msg) { - if (msg instanceof ReferenceCounted) { - return (T) ((ReferenceCounted) msg).retain(); - } - return msg; - } - - /** - * Try to call {@link ReferenceCounted#retain()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - - public static T retain(T msg, int increment) { - if (msg instanceof ReferenceCounted) { - return (T) ((ReferenceCounted) msg).retain(increment); - } - return msg; - } - - /** - * Try to call {@link ReferenceCounted#release()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - public static boolean release(Object msg) { - if (msg instanceof ReferenceCounted) { - return ((ReferenceCounted) msg).release(); - } - return false; - } - - /** - * Try to call {@link ReferenceCounted#release(int)} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - public static boolean release(Object msg, int decrement) { - if (msg instanceof ReferenceCounted) { - return ((ReferenceCounted) msg).release(decrement); - } - return false; - } - - /** - * Try to call {@link ReferenceCounted#release()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - * Unlike {@link #release(Object)} this method catches an exception raised by {@link ReferenceCounted#release()} - * and logs it, rather than rethrowing it to the caller. It is usually recommended to use {@link #release(Object)} - * instead, unless you absolutely need to swallow an exception. - */ - public static void safeRelease(Object msg) { - try { - release(msg); - } catch (Throwable t) { - logger.warn("Failed to release a message: {}", msg, t); - } - } - - /** - * Try to call {@link ReferenceCounted#release(int)} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - * Unlike {@link #release(Object)} this method catches an exception raised by {@link ReferenceCounted#release(int)} - * and logs it, rather than rethrowing it to the caller. It is usually recommended to use - * {@link #release(Object, int)} instead, unless you absolutely need to swallow an exception. - */ - public static void safeRelease(Object msg, int decrement) { - try { - release(msg, decrement); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to release a message: {} (decrement: {})", msg, decrement, t); - } - } - } - - /** - * Schedules the specified object to be released when the caller thread terminates. Note that this operation is - * intended to simplify reference counting of ephemeral objects during unit tests. Do not use it beyond the - * intended use case. - */ - public static T releaseLater(T msg) { - return releaseLater(msg, 1); - } - - /** - * Schedules the specified object to be released when the caller thread terminates. Note that this operation is - * intended to simplify reference counting of ephemeral objects during unit tests. Do not use it beyond the - * intended use case. - */ - public static T releaseLater(T msg, int decrement) { - if (msg instanceof ReferenceCounted) { - ThreadDeathWatcher.watch(Thread.currentThread(), new ReleasingTask((ReferenceCounted) msg, decrement)); - } - return msg; - } - - /** - * Releases the objects when the thread that called {@link #releaseLater(Object)} has been terminated. - */ - private static final class ReleasingTask implements Runnable { - - private final ReferenceCounted obj; - private final int decrement; - - ReleasingTask(ReferenceCounted obj, int decrement) { - this.obj = obj; - this.decrement = decrement; - } - - @Override - public void run() { - try { - if (!obj.release(decrement)) { - logger.warn("Non-zero refCnt: {}", this); - } else { - logger.debug("Released: {}", this); - } - } catch (Exception ex) { - logger.warn("Failed to release an object: {}", obj, ex); - } - } - - @Override - public String toString() { - return StringUtil.simpleClassName(obj) + ".release(" + decrement + ") refCnt: " + obj.refCnt(); - } - } - - private ReferenceCountUtil() { } -} diff --git a/java/src/game/net/util/ReferenceCounted.java b/java/src/game/net/util/ReferenceCounted.java deleted file mode 100644 index 22c36c3..0000000 --- a/java/src/game/net/util/ReferenceCounted.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -/** - * A reference-counted object that requires explicit deallocation. - *

- * When a new {@link ReferenceCounted} is instantiated, it starts with the reference count of {@code 1}. - * {@link #retain()} increases the reference count, and {@link #release()} decreases the reference count. - * If the reference count is decreased to {@code 0}, the object will be deallocated explicitly, and accessing - * the deallocated object will usually result in an access violation. - *

- *

- * If an object that implements {@link ReferenceCounted} is a container of other objects that implement - * {@link ReferenceCounted}, the contained objects will also be released via {@link #release()} when the container's - * reference count becomes 0. - *

- */ -public interface ReferenceCounted { - /** - * Returns the reference count of this object. If {@code 0}, it means this object has been deallocated. - */ - int refCnt(); - - /** - * Increases the reference count by {@code 1}. - */ - ReferenceCounted retain(); - - /** - * Increases the reference count by the specified {@code increment}. - */ - ReferenceCounted retain(int increment); - - /** - * Decreases the reference count by {@code 1} and deallocates this object if the reference count reaches at - * {@code 0}. - * - * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated - */ - boolean release(); - - /** - * Decreases the reference count by the specified {@code decrement} and deallocates this object if the reference - * count reaches at {@code 0}. - * - * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated - */ - boolean release(int decrement); -} diff --git a/java/src/game/net/util/ResourceLeak.java b/java/src/game/net/util/ResourceLeak.java deleted file mode 100644 index 22d2210..0000000 --- a/java/src/game/net/util/ResourceLeak.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util; - -public interface ResourceLeak { - /** - * Records the caller's current stack trace so that the {@link ResourceLeakDetector} can tell where the leaked - * resource was accessed lastly. - */ - void record(); - - /** - * Close the leak so that {@link ResourceLeakDetector} does not warn about leaked resources. - * - * @return {@code true} if called first time, {@code false} if called already - */ - boolean close(); -} diff --git a/java/src/game/net/util/ResourceLeakDetector.java b/java/src/game/net/util/ResourceLeakDetector.java deleted file mode 100644 index 4b1b1bf..0000000 --- a/java/src/game/net/util/ResourceLeakDetector.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util; - -import static game.net.util.internal.StringUtil.NEWLINE; -import static game.net.util.internal.StringUtil.simpleClassName; - -import java.lang.ref.PhantomReference; -import java.lang.ref.ReferenceQueue; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.EnumSet; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicBoolean; - -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.SystemPropertyUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -public final class ResourceLeakDetector { - - private static final String PROP_LEVEL = "io.netty.leakDetectionLevel"; - private static final Level DEFAULT_LEVEL = Level.SIMPLE; - - /** - * Represents the level of resource leak detection. - */ - public enum Level { - /** - * Disables resource leak detection. - */ - DISABLED, - /** - * Enables simplistic sampling resource leak detection which reports there is a leak or not, - * at the cost of small overhead (default). - */ - SIMPLE, - /** - * Enables advanced sampling resource leak detection which reports where the leaked object was accessed - * recently at the cost of high overhead. - */ - ADVANCED, - /** - * Enables paranoid resource leak detection which reports where the leaked object was accessed recently, - * at the cost of the highest possible overhead (for testing purposes only). - */ - PARANOID - } - - private static Level level; - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ResourceLeakDetector.class); - - static { - final boolean disabled; - if (SystemPropertyUtil.get("io.netty.noResourceLeakDetection") != null) { - disabled = SystemPropertyUtil.getBoolean("io.netty.noResourceLeakDetection", false); - logger.debug("-Dio.netty.noResourceLeakDetection: {}", disabled); - logger.warn( - "-Dio.netty.noResourceLeakDetection is deprecated. Use '-D{}={}' instead.", - PROP_LEVEL, DEFAULT_LEVEL.name().toLowerCase()); - } else { - disabled = false; - } - - Level defaultLevel = disabled? Level.DISABLED : DEFAULT_LEVEL; - String levelStr = SystemPropertyUtil.get(PROP_LEVEL, defaultLevel.name()).trim().toUpperCase(); - Level level = DEFAULT_LEVEL; - for (Level l: EnumSet.allOf(Level.class)) { - if (levelStr.equals(l.name()) || levelStr.equals(String.valueOf(l.ordinal()))) { - level = l; - } - } - - ResourceLeakDetector.level = level; - if (logger.isDebugEnabled()) { - logger.debug("-D{}: {}", PROP_LEVEL, level.name().toLowerCase()); - } - } - - private static final int DEFAULT_SAMPLING_INTERVAL = 113; - - /** - * @deprecated Use {@link #setLevel(Level)} instead. - */ - @Deprecated - public static void setEnabled(boolean enabled) { - setLevel(enabled? Level.SIMPLE : Level.DISABLED); - } - - /** - * Returns {@code true} if resource leak detection is enabled. - */ - public static boolean isEnabled() { - return getLevel().ordinal() > Level.DISABLED.ordinal(); - } - - /** - * Sets the resource leak detection level. - */ - public static void setLevel(Level level) { - if (level == null) { - throw new NullPointerException("level"); - } - ResourceLeakDetector.level = level; - } - - /** - * Returns the current resource leak detection level. - */ - public static Level getLevel() { - return level; - } - - /** the linked list of active resources */ - private final DefaultResourceLeak head = new DefaultResourceLeak(null); - private final DefaultResourceLeak tail = new DefaultResourceLeak(null); - - private final ReferenceQueue refQueue = new ReferenceQueue(); - private final ConcurrentMap reportedLeaks = PlatformDependent.newConcurrentHashMap(); - - private final String resourceType; - private final int samplingInterval; - private final long maxActive; - private long active; - private final AtomicBoolean loggedTooManyActive = new AtomicBoolean(); - - private long leakCheckCnt; - - public ResourceLeakDetector(Class resourceType) { - this(simpleClassName(resourceType)); - } - - public ResourceLeakDetector(String resourceType) { - this(resourceType, DEFAULT_SAMPLING_INTERVAL, Long.MAX_VALUE); - } - - public ResourceLeakDetector(Class resourceType, int samplingInterval, long maxActive) { - this(simpleClassName(resourceType), samplingInterval, maxActive); - } - - public ResourceLeakDetector(String resourceType, int samplingInterval, long maxActive) { - if (resourceType == null) { - throw new NullPointerException("resourceType"); - } - if (samplingInterval <= 0) { - throw new IllegalArgumentException("samplingInterval: " + samplingInterval + " (expected: 1+)"); - } - if (maxActive <= 0) { - throw new IllegalArgumentException("maxActive: " + maxActive + " (expected: 1+)"); - } - - this.resourceType = resourceType; - this.samplingInterval = samplingInterval; - this.maxActive = maxActive; - - head.next = tail; - tail.prev = head; - } - - /** - * Creates a new {@link ResourceLeak} which is expected to be closed via {@link ResourceLeak#close()} when the - * related resource is deallocated. - * - * @return the {@link ResourceLeak} or {@code null} - */ - public ResourceLeak open(T obj) { - Level level = ResourceLeakDetector.level; - if (level == Level.DISABLED) { - return null; - } - - if (level.ordinal() < Level.PARANOID.ordinal()) { - if (leakCheckCnt ++ % samplingInterval == 0) { - reportLeak(level); - return new DefaultResourceLeak(obj); - } else { - return null; - } - } else { - reportLeak(level); - return new DefaultResourceLeak(obj); - } - } - - private void reportLeak(Level level) { - if (!logger.isErrorEnabled()) { - for (;;) { - - DefaultResourceLeak ref = (DefaultResourceLeak) refQueue.poll(); - if (ref == null) { - break; - } - ref.close(); - } - return; - } - - // Report too many instances. - int samplingInterval = level == Level.PARANOID? 1 : this.samplingInterval; - if (active * samplingInterval > maxActive && loggedTooManyActive.compareAndSet(false, true)) { - logger.error("LEAK: You are creating too many " + resourceType + " instances. " + - resourceType + " is a shared resource that must be reused across the JVM," + - "so that only a few instances are created."); - } - - // Detect and report previous leaks. - for (;;) { - - DefaultResourceLeak ref = (DefaultResourceLeak) refQueue.poll(); - if (ref == null) { - break; - } - - ref.clear(); - - if (!ref.close()) { - continue; - } - - String records = ref.toString(); - if (reportedLeaks.putIfAbsent(records, Boolean.TRUE) == null) { - if (records.isEmpty()) { - logger.error("LEAK: {}.release() was not called before it's garbage-collected. " + - "Enable advanced leak reporting to find out where the leak occurred. " + - "To enable advanced leak reporting, " + - "specify the JVM option '-D{}={}' or call {}.setLevel()", - resourceType, PROP_LEVEL, Level.ADVANCED.name().toLowerCase(), simpleClassName(this)); - } else { - logger.error( - "LEAK: {}.release() was not called before it's garbage-collected.{}", - resourceType, records); - } - } - } - } - - private final class DefaultResourceLeak extends PhantomReference implements ResourceLeak { - - private static final int MAX_RECORDS = 4; - - private final String creationRecord; - private final Deque lastRecords = new ArrayDeque(); - private final AtomicBoolean freed; - private DefaultResourceLeak prev; - private DefaultResourceLeak next; - - DefaultResourceLeak(Object referent) { - super(referent, referent != null? refQueue : null); - - if (referent != null) { - Level level = getLevel(); - if (level.ordinal() >= Level.ADVANCED.ordinal()) { - creationRecord = newRecord(3); - } else { - creationRecord = null; - } - - // TODO: Use CAS to update the list. - synchronized (head) { - prev = head; - next = head.next; - head.next.prev = this; - head.next = this; - active ++; - } - freed = new AtomicBoolean(); - } else { - creationRecord = null; - freed = new AtomicBoolean(true); - } - } - - @Override - public void record() { - if (creationRecord != null) { - String value = newRecord(2); - - synchronized (lastRecords) { - int size = lastRecords.size(); - if (size == 0 || !lastRecords.getLast().equals(value)) { - lastRecords.add(value); - } - if (size > MAX_RECORDS) { - lastRecords.removeFirst(); - } - } - } - } - - @Override - public boolean close() { - if (freed.compareAndSet(false, true)) { - synchronized (head) { - active --; - prev.next = next; - next.prev = prev; - prev = null; - next = null; - } - return true; - } - return false; - } - - public String toString() { - if (creationRecord == null) { - return ""; - } - - Object[] array; - synchronized (lastRecords) { - array = lastRecords.toArray(); - } - - StringBuilder buf = new StringBuilder(16384); - buf.append(NEWLINE); - buf.append("Recent access records: "); - buf.append(array.length); - buf.append(NEWLINE); - - if (array.length > 0) { - for (int i = array.length - 1; i >= 0; i --) { - buf.append('#'); - buf.append(i + 1); - buf.append(':'); - buf.append(NEWLINE); - buf.append(array[i]); - } - } - - buf.append("Created at:"); - buf.append(NEWLINE); - buf.append(creationRecord); - buf.setLength(buf.length() - NEWLINE.length()); - - return buf.toString(); - } - } - - private static final String[] STACK_TRACE_ELEMENT_EXCLUSIONS = { - "io.netty.buffer.AbstractByteBufAllocator.toLeakAwareBuffer(", - }; - - static String newRecord(int recordsToSkip) { - StringBuilder buf = new StringBuilder(4096); - StackTraceElement[] array = new Throwable().getStackTrace(); - for (StackTraceElement e: array) { - if (recordsToSkip > 0) { - recordsToSkip --; - } else { - String estr = e.toString(); - - // Strip the noisy stack trace elements. - boolean excluded = false; - for (String exclusion: STACK_TRACE_ELEMENT_EXCLUSIONS) { - if (estr.startsWith(exclusion)) { - excluded = true; - break; - } - } - - if (!excluded) { - buf.append('\t'); - buf.append(estr); - buf.append(NEWLINE); - } - } - } - - return buf.toString(); - } -} diff --git a/java/src/game/net/util/Signal.java b/java/src/game/net/util/Signal.java deleted file mode 100644 index 8ba42b5..0000000 --- a/java/src/game/net/util/Signal.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - - -import java.util.concurrent.ConcurrentMap; - -import game.net.util.internal.PlatformDependent; - -/** - * A special {@link Error} which is used to signal some state or request by throwing it. - * {@link Signal} has an empty stack trace and has no cause to save the instantiation overhead. - */ -public final class Signal extends Error { - - private static final long serialVersionUID = -221145131122459977L; - - private static final ConcurrentMap map = PlatformDependent.newConcurrentHashMap(); - - - private final UniqueName uname; - - /** - * Creates a new {@link Signal} with the specified {@code name}. - */ - - public static Signal valueOf(String name) { - return new Signal(name); - } - - /** - * @deprecated Use {@link #valueOf(String)} instead. - */ - @Deprecated - public Signal(String name) { - super(name); - uname = new UniqueName(map, name); - } - - /** - * Check if the given {@link Signal} is the same as this instance. If not an {@link IllegalStateException} will - * be thrown. - */ - public void expect(Signal signal) { - if (this != signal) { - throw new IllegalStateException("unexpected signal: " + signal); - } - } - - @Override - public Throwable initCause(Throwable cause) { - return this; - } - - @Override - public Throwable fillInStackTrace() { - return this; - } - - @Override - public String toString() { - return uname.name(); - } -} diff --git a/java/src/game/net/util/ThreadDeathWatcher.java b/java/src/game/net/util/ThreadDeathWatcher.java deleted file mode 100644 index e150915..0000000 --- a/java/src/game/net/util/ThreadDeathWatcher.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import game.net.util.concurrent.DefaultThreadFactory; -import game.net.util.internal.MpscLinkedQueueNode; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Checks if a thread is alive periodically and runs a task when a thread dies. - *

- * This thread starts a daemon thread to check the state of the threads being watched and to invoke their - * associated {@link Runnable}s. When there is no thread to watch (i.e. all threads are dead), the daemon thread - * will terminate itself, and a new daemon thread will be started again when a new watch is added. - *

- */ -public final class ThreadDeathWatcher { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ThreadDeathWatcher.class); - private static final ThreadFactory threadFactory = - new DefaultThreadFactory(ThreadDeathWatcher.class, true, Thread.MIN_PRIORITY); - - private static final Queue pendingEntries = PlatformDependent.newMpscQueue(); - private static final Watcher watcher = new Watcher(); - private static final AtomicBoolean started = new AtomicBoolean(); - private static volatile Thread watcherThread; - - /** - * Schedules the specified {@code task} to run when the specified {@code thread} dies. - * - * @param thread the {@link Thread} to watch - * @param task the {@link Runnable} to run when the {@code thread} dies - * - * @throws IllegalArgumentException if the specified {@code thread} is not alive - */ - public static void watch(Thread thread, Runnable task) { - if (thread == null) { - throw new NullPointerException("thread"); - } - if (task == null) { - throw new NullPointerException("task"); - } - if (!thread.isAlive()) { - throw new IllegalArgumentException("thread must be alive."); - } - - schedule(thread, task, true); - } - - /** - * Cancels the task scheduled via {@link #watch(Thread, Runnable)}. - */ - public static void unwatch(Thread thread, Runnable task) { - if (thread == null) { - throw new NullPointerException("thread"); - } - if (task == null) { - throw new NullPointerException("task"); - } - - schedule(thread, task, false); - } - - private static void schedule(Thread thread, Runnable task, boolean isWatch) { - pendingEntries.add(new Entry(thread, task, isWatch)); - - if (started.compareAndSet(false, true)) { - Thread watcherThread = threadFactory.newThread(watcher); - watcherThread.start(); - ThreadDeathWatcher.watcherThread = watcherThread; - } - } - - /** - * Waits until the thread of this watcher has no threads to watch and terminates itself. - * Because a new watcher thread will be started again on {@link #watch(Thread, Runnable)}, - * this operation is only useful when you want to ensure that the watcher thread is terminated - * after your application is shut down and there's no chance of calling - * {@link #watch(Thread, Runnable)} afterwards. - * - * @return {@code true} if and only if the watcher thread has been terminated - */ - public static boolean awaitInactivity(long timeout, TimeUnit unit) throws InterruptedException { - if (unit == null) { - throw new NullPointerException("unit"); - } - - Thread watcherThread = ThreadDeathWatcher.watcherThread; - if (watcherThread != null) { - watcherThread.join(unit.toMillis(timeout)); - return !watcherThread.isAlive(); - } else { - return true; - } - } - - private ThreadDeathWatcher() { } - - private static final class Watcher implements Runnable { - - private final List watchees = new ArrayList(); - - @Override - public void run() { - for (;;) { - fetchWatchees(); - notifyWatchees(); - - // Try once again just in case notifyWatchees() triggered watch() or unwatch(). - fetchWatchees(); - notifyWatchees(); - - try { - Thread.sleep(1000); - } catch (InterruptedException ignore) { - // Ignore the interrupt; do not terminate until all tasks are run. - } - - if (watchees.isEmpty() && pendingEntries.isEmpty()) { - - // Mark the current worker thread as stopped. - // The following CAS must always success and must be uncontended, - // because only one watcher thread should be running at the same time. - boolean stopped = started.compareAndSet(true, false); - assert stopped; - - // Check if there are pending entries added by watch() while we do CAS above. - if (pendingEntries.isEmpty()) { - // A) watch() was not invoked and thus there's nothing to handle - // -> safe to terminate because there's nothing left to do - // B) a new watcher thread started and handled them all - // -> safe to terminate the new watcher thread will take care the rest - break; - } - - // There are pending entries again, added by watch() - if (!started.compareAndSet(false, true)) { - // watch() started a new watcher thread and set 'started' to true. - // -> terminate this thread so that the new watcher reads from pendingEntries exclusively. - break; - } - - // watch() added an entry, but this worker was faster to set 'started' to true. - // i.e. a new watcher thread was not started - // -> keep this thread alive to handle the newly added entries. - } - } - } - - private void fetchWatchees() { - for (;;) { - Entry e = pendingEntries.poll(); - if (e == null) { - break; - } - - if (e.isWatch) { - watchees.add(e); - } else { - watchees.remove(e); - } - } - } - - private void notifyWatchees() { - List watchees = this.watchees; - for (int i = 0; i < watchees.size();) { - Entry e = watchees.get(i); - if (!e.thread.isAlive()) { - watchees.remove(i); - try { - e.task.run(); - } catch (Throwable t) { - logger.warn("Thread death watcher task raised an exception:", t); - } - } else { - i ++; - } - } - } - } - - private static final class Entry extends MpscLinkedQueueNode { - final Thread thread; - final Runnable task; - final boolean isWatch; - - Entry(Thread thread, Runnable task, boolean isWatch) { - this.thread = thread; - this.task = task; - this.isWatch = isWatch; - } - - @Override - public Entry value() { - return this; - } - - @Override - public int hashCode() { - return thread.hashCode() ^ task.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof Entry)) { - return false; - } - - Entry that = (Entry) obj; - return thread == that.thread && task == that.task; - } - } -} diff --git a/java/src/game/net/util/UniqueName.java b/java/src/game/net/util/UniqueName.java deleted file mode 100644 index 7858486..0000000 --- a/java/src/game/net/util/UniqueName.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util; - -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @deprecated Known to have problems with class loaders. - * - * Defines a name that must be unique in the map that is provided during construction. - */ -@Deprecated -public class UniqueName implements Comparable { - - private static final AtomicInteger nextId = new AtomicInteger(); - - private final int id; - private final String name; - - /** - * Constructs a new {@link UniqueName} - * - * @param map the map of names to compare with - * @param name the name of this {@link UniqueName} - * @param args the arguments to process - */ - public UniqueName(ConcurrentMap map, String name, Object... args) { - if (map == null) { - throw new NullPointerException("map"); - } - if (name == null) { - throw new NullPointerException("name"); - } - if (args != null && args.length > 0) { - validateArgs(args); - } - - if (map.putIfAbsent(name, Boolean.TRUE) != null) { - throw new IllegalArgumentException(String.format("'%s' is already in use", name)); - } - - id = nextId.incrementAndGet(); - this.name = name; - } - - /** - * Validates the given arguments. This method does not do anything on its own, but must be - * overridden by its subclasses. - * - * @param args arguments to validate - */ - - protected void validateArgs(Object... args) { - // Subclasses will override. - } - - /** - * Returns this {@link UniqueName}'s name - * - * @return the name - */ - public final String name() { - return name; - } - - /** - * Returns this {@link UniqueName}'s ID - * - * @return the id - */ - public final int id() { - return id; - } - - @Override - public final int hashCode() { - return super.hashCode(); - } - - @Override - public final boolean equals(Object o) { - return super.equals(o); - } - - @Override - public int compareTo(UniqueName other) { - if (this == other) { - return 0; - } - - int returnCode = name.compareTo(other.name); - if (returnCode != 0) { - return returnCode; - } - - return ((Integer) id).compareTo(other.id); - } - - @Override - public String toString() { - return name(); - } -} diff --git a/java/src/game/net/util/concurrent/AbstractEventExecutor.java b/java/src/game/net/util/concurrent/AbstractEventExecutor.java deleted file mode 100644 index 1cec283..0000000 --- a/java/src/game/net/util/concurrent/AbstractEventExecutor.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.concurrent.AbstractExecutorService; -import java.util.concurrent.Callable; -import java.util.concurrent.RunnableFuture; -import java.util.concurrent.TimeUnit; - -/** - * Abstract base class for {@link EventExecutor} implementations. - */ -public abstract class AbstractEventExecutor extends AbstractExecutorService implements EventExecutor { - - @Override - public EventExecutor next() { - return this; - } - - @Override - public boolean inEventLoop() { - return inEventLoop(Thread.currentThread()); - } - - @Override - public Iterator iterator() { - return new EventExecutorIterator(); - } - - @Override - public Future shutdownGracefully() { - return shutdownGracefully(2, 15, TimeUnit.SECONDS); - } - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public abstract void shutdown(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public List shutdownNow() { - shutdown(); - return Collections.emptyList(); - } - - @Override - public Promise newPromise() { - return new DefaultPromise(this); - } - - @Override - public ProgressivePromise newProgressivePromise() { - return new DefaultProgressivePromise(this); - } - - @Override - public Future newSucceededFuture(V result) { - return new SucceededFuture(this, result); - } - - @Override - public Future newFailedFuture(Throwable cause) { - return new FailedFuture(this, cause); - } - - @Override - public Future submit(Runnable task) { - return (Future) super.submit(task); - } - - @Override - public Future submit(Runnable task, T result) { - return (Future) super.submit(task, result); - } - - @Override - public Future submit(Callable task) { - return (Future) super.submit(task); - } - - @Override - protected final RunnableFuture newTaskFor(Runnable runnable, T value) { - return new PromiseTask(this, runnable, value); - } - - @Override - protected final RunnableFuture newTaskFor(Callable callable) { - return new PromiseTask(this, callable); - } - - @Override - public ScheduledFuture schedule(Runnable command, long delay, - TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - private final class EventExecutorIterator implements Iterator { - private boolean nextCalled; - - @Override - public boolean hasNext() { - return !nextCalled; - } - - @Override - public EventExecutor next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - nextCalled = true; - return AbstractEventExecutor.this; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("read-only"); - } - } -} diff --git a/java/src/game/net/util/concurrent/AbstractEventExecutorGroup.java b/java/src/game/net/util/concurrent/AbstractEventExecutorGroup.java deleted file mode 100644 index 5a3b5f2..0000000 --- a/java/src/game/net/util/concurrent/AbstractEventExecutorGroup.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - - -/** - * Abstract base class for {@link EventExecutorGroup} implementations. - */ -public abstract class AbstractEventExecutorGroup implements EventExecutorGroup { - - @Override - public Future submit(Runnable task) { - return next().submit(task); - } - - @Override - public Future submit(Runnable task, T result) { - return next().submit(task, result); - } - - @Override - public Future submit(Callable task) { - return next().submit(task); - } - - @Override - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { - return next().schedule(command, delay, unit); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - return next().schedule(callable, delay, unit); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - return next().scheduleAtFixedRate(command, initialDelay, period, unit); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - return next().scheduleWithFixedDelay(command, initialDelay, delay, unit); - } - - @Override - public Future shutdownGracefully() { - return shutdownGracefully(2, 15, TimeUnit.SECONDS); - } - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public abstract void shutdown(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public List shutdownNow() { - shutdown(); - return Collections.emptyList(); - } - - @Override - public List> invokeAll(Collection> tasks) - throws InterruptedException { - return next().invokeAll(tasks); - } - - @Override - public List> invokeAll( - Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { - return next().invokeAll(tasks, timeout, unit); - } - - @Override - public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { - return next().invokeAny(tasks); - } - - @Override - public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return next().invokeAny(tasks, timeout, unit); - } - - @Override - public void execute(Runnable command) { - next().execute(command); - } -} diff --git a/java/src/game/net/util/concurrent/AbstractFuture.java b/java/src/game/net/util/concurrent/AbstractFuture.java deleted file mode 100644 index 4a4252a..0000000 --- a/java/src/game/net/util/concurrent/AbstractFuture.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Abstract {@link Future} implementation which does not allow for cancellation. - * - * @param - */ -public abstract class AbstractFuture implements Future { - - @Override - public V get() throws InterruptedException, ExecutionException { - await(); - - Throwable cause = cause(); - if (cause == null) { - return getNow(); - } - throw new ExecutionException(cause); - } - - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - if (await(timeout, unit)) { - Throwable cause = cause(); - if (cause == null) { - return getNow(); - } - throw new ExecutionException(cause); - } - throw new TimeoutException(); - } -} diff --git a/java/src/game/net/util/concurrent/BlockingOperationException.java b/java/src/game/net/util/concurrent/BlockingOperationException.java deleted file mode 100644 index deee409..0000000 --- a/java/src/game/net/util/concurrent/BlockingOperationException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -/** - * An {@link IllegalStateException} which is raised when a user performed a blocking operation - * when the user is in an event loop thread. If a blocking operation is performed in an event loop - * thread, the blocking operation will most likely enter a dead lock state, hence throwing this - * exception. - */ -public class BlockingOperationException extends IllegalStateException { - - private static final long serialVersionUID = 2462223247762460301L; - - public BlockingOperationException() { } - - public BlockingOperationException(String s) { - super(s); - } - - public BlockingOperationException(Throwable cause) { - super(cause); - } - - public BlockingOperationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/java/src/game/net/util/concurrent/CompleteFuture.java b/java/src/game/net/util/concurrent/CompleteFuture.java deleted file mode 100644 index 0b4ccd2..0000000 --- a/java/src/game/net/util/concurrent/CompleteFuture.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.concurrent; - -import java.util.concurrent.TimeUnit; - -/** - * A skeletal {@link Future} implementation which represents a {@link Future} which has been completed already. - */ -public abstract class CompleteFuture extends AbstractFuture { - - private final EventExecutor executor; - - /** - * Creates a new instance. - * - * @param executor the {@link EventExecutor} associated with this future - */ - protected CompleteFuture(EventExecutor executor) { - this.executor = executor; - } - - /** - * Return the {@link EventExecutor} which is used by this {@link CompleteFuture}. - */ - protected EventExecutor executor() { - return executor; - } - - @Override - public Future addListener(GenericFutureListener> listener) { - if (listener == null) { - throw new NullPointerException("listener"); - } - DefaultPromise.notifyListener(executor(), this, listener); - return this; - } - - @Override - public Future addListeners(GenericFutureListener>... listeners) { - if (listeners == null) { - throw new NullPointerException("listeners"); - } - for (GenericFutureListener> l: listeners) { - if (l == null) { - break; - } - DefaultPromise.notifyListener(executor(), this, l); - } - return this; - } - - @Override - public Future removeListener(GenericFutureListener> listener) { - // NOOP - return this; - } - - @Override - public Future removeListeners(GenericFutureListener>... listeners) { - // NOOP - return this; - } - - @Override - public Future await() throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return this; - } - - @Override - public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return true; - } - - @Override - public Future sync() throws InterruptedException { - return this; - } - - @Override - public Future syncUninterruptibly() { - return this; - } - - @Override - public boolean await(long timeoutMillis) throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return true; - } - - @Override - public Future awaitUninterruptibly() { - return this; - } - - @Override - public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - return true; - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - return true; - } - - @Override - public boolean isDone() { - return true; - } - - @Override - public boolean isCancellable() { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } -} diff --git a/java/src/game/net/util/concurrent/DefaultEventExecutor.java b/java/src/game/net/util/concurrent/DefaultEventExecutor.java deleted file mode 100644 index c5432d2..0000000 --- a/java/src/game/net/util/concurrent/DefaultEventExecutor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.concurrent.ThreadFactory; - -/** - * Default {@link SingleThreadEventExecutor} implementation which just execute all submitted task in a - * serial fashion - * - */ -final class DefaultEventExecutor extends SingleThreadEventExecutor { - - DefaultEventExecutor(DefaultEventExecutorGroup parent, ThreadFactory threadFactory) { - super(parent, threadFactory, true); - } - - @Override - protected void run() { - for (;;) { - Runnable task = takeTask(); - if (task != null) { - task.run(); - updateLastExecutionTime(); - } - - if (confirmShutdown()) { - break; - } - } - } -} diff --git a/java/src/game/net/util/concurrent/DefaultEventExecutorGroup.java b/java/src/game/net/util/concurrent/DefaultEventExecutorGroup.java deleted file mode 100644 index ca14e21..0000000 --- a/java/src/game/net/util/concurrent/DefaultEventExecutorGroup.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.concurrent.ThreadFactory; - -/** - * Default implementation of {@link MultithreadEventExecutorGroup} which will use {@link DefaultEventExecutor} instances - * to handle the tasks. - */ -public class DefaultEventExecutorGroup extends MultithreadEventExecutorGroup { - - /** - * @see {@link #DefaultEventExecutorGroup(int, ThreadFactory)} - */ - public DefaultEventExecutorGroup(int nThreads) { - this(nThreads, null); - } - - /** - * Create a new instance. - * - * @param nThreads the number of threads that will be used by this instance. - * @param threadFactory the ThreadFactory to use, or {@code null} if the default should be used. - */ - public DefaultEventExecutorGroup(int nThreads, ThreadFactory threadFactory) { - super(nThreads, threadFactory); - } - - @Override - protected EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception { - return new DefaultEventExecutor(this, threadFactory); - } -} diff --git a/java/src/game/net/util/concurrent/DefaultFutureListeners.java b/java/src/game/net/util/concurrent/DefaultFutureListeners.java deleted file mode 100644 index 84b8062..0000000 --- a/java/src/game/net/util/concurrent/DefaultFutureListeners.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.Arrays; - -final class DefaultFutureListeners { - - private GenericFutureListener>[] listeners; - private int size; - private int progressiveSize; // the number of progressive listeners - - - DefaultFutureListeners( - GenericFutureListener> first, GenericFutureListener> second) { - listeners = new GenericFutureListener[2]; - listeners[0] = first; - listeners[1] = second; - size = 2; - if (first instanceof GenericProgressiveFutureListener) { - progressiveSize ++; - } - if (second instanceof GenericProgressiveFutureListener) { - progressiveSize ++; - } - } - - public void add(GenericFutureListener> l) { - GenericFutureListener>[] listeners = this.listeners; - final int size = this.size; - if (size == listeners.length) { - this.listeners = listeners = Arrays.copyOf(listeners, size << 1); - } - listeners[size] = l; - this.size = size + 1; - - if (l instanceof GenericProgressiveFutureListener) { - progressiveSize ++; - } - } - - public void remove(GenericFutureListener> l) { - final GenericFutureListener>[] listeners = this.listeners; - int size = this.size; - for (int i = 0; i < size; i ++) { - if (listeners[i] == l) { - int listenersToMove = size - i - 1; - if (listenersToMove > 0) { - System.arraycopy(listeners, i + 1, listeners, i, listenersToMove); - } - listeners[-- size] = null; - this.size = size; - - if (l instanceof GenericProgressiveFutureListener) { - progressiveSize --; - } - return; - } - } - } - - public GenericFutureListener>[] listeners() { - return listeners; - } - - public int size() { - return size; - } - - public int progressiveSize() { - return progressiveSize; - } -} diff --git a/java/src/game/net/util/concurrent/DefaultProgressivePromise.java b/java/src/game/net/util/concurrent/DefaultProgressivePromise.java deleted file mode 100644 index d02c7c9..0000000 --- a/java/src/game/net/util/concurrent/DefaultProgressivePromise.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.concurrent; - -public class DefaultProgressivePromise extends DefaultPromise implements ProgressivePromise { - - /** - * Creates a new instance. - * - * It is preferable to use {@link EventExecutor#newProgressivePromise()} to create a new progressive promise - * - * @param executor - * the {@link EventExecutor} which is used to notify the promise when it progresses or it is complete - */ - public DefaultProgressivePromise(EventExecutor executor) { - super(executor); - } - - protected DefaultProgressivePromise() { /* only for subclasses */ } - - @Override - public ProgressivePromise setProgress(long progress, long total) { - if (total < 0) { - // total unknown - total = -1; // normalize - if (progress < 0) { - throw new IllegalArgumentException("progress: " + progress + " (expected: >= 0)"); - } - } else if (progress < 0 || progress > total) { - throw new IllegalArgumentException( - "progress: " + progress + " (expected: 0 <= progress <= total (" + total + "))"); - } - - if (isDone()) { - throw new IllegalStateException("complete already"); - } - - notifyProgressiveListeners(progress, total); - return this; - } - - @Override - public boolean tryProgress(long progress, long total) { - if (total < 0) { - total = -1; - if (progress < 0 || isDone()) { - return false; - } - } else if (progress < 0 || progress > total || isDone()) { - return false; - } - - notifyProgressiveListeners(progress, total); - return true; - } - - @Override - public ProgressivePromise addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public ProgressivePromise addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public ProgressivePromise removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public ProgressivePromise removeListeners(GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public ProgressivePromise sync() throws InterruptedException { - super.sync(); - return this; - } - - @Override - public ProgressivePromise syncUninterruptibly() { - super.syncUninterruptibly(); - return this; - } - - @Override - public ProgressivePromise await() throws InterruptedException { - super.await(); - return this; - } - - @Override - public ProgressivePromise awaitUninterruptibly() { - super.awaitUninterruptibly(); - return this; - } - - @Override - public ProgressivePromise setSuccess(V result) { - super.setSuccess(result); - return this; - } - - @Override - public ProgressivePromise setFailure(Throwable cause) { - super.setFailure(cause); - return this; - } -} diff --git a/java/src/game/net/util/concurrent/DefaultPromise.java b/java/src/game/net/util/concurrent/DefaultPromise.java deleted file mode 100644 index 9797ded..0000000 --- a/java/src/game/net/util/concurrent/DefaultPromise.java +++ /dev/null @@ -1,876 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.util.ArrayDeque; -import java.util.concurrent.CancellationException; -import java.util.concurrent.TimeUnit; - -import game.net.util.Signal; -import game.net.util.internal.EmptyArrays; -import game.net.util.internal.InternalThreadLocalMap; -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.StringUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -public class DefaultPromise extends AbstractFuture implements Promise { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultPromise.class); - private static final InternalLogger rejectedExecutionLogger = - InternalLoggerFactory.getInstance(DefaultPromise.class.getName() + ".rejectedExecution"); - - private static final int MAX_LISTENER_STACK_DEPTH = 8; - private static final Signal SUCCESS = Signal.valueOf(DefaultPromise.class.getName() + ".SUCCESS"); - private static final Signal UNCANCELLABLE = Signal.valueOf(DefaultPromise.class.getName() + ".UNCANCELLABLE"); - private static final CauseHolder CANCELLATION_CAUSE_HOLDER = new CauseHolder(new CancellationException()); - - static { - CANCELLATION_CAUSE_HOLDER.cause.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - private final EventExecutor executor; - - private volatile Object result; - - /** - * One or more listeners. Can be a {@link GenericFutureListener} or a {@link DefaultFutureListeners}. - * If {@code null}, it means either 1) no listeners were added yet or 2) all listeners were notified. - */ - private Object listeners; - - /** - * The list of the listeners that were added after the promise is done. Initially {@code null} and lazily - * instantiated when the late listener is scheduled to be notified later. Also used as a cached {@link Runnable} - * that performs the notification of the listeners it contains. - */ - private LateListeners lateListeners; - - private short waiters; - - /** - * Creates a new instance. - * - * It is preferable to use {@link EventExecutor#newPromise()} to create a new promise - * - * @param executor - * the {@link EventExecutor} which is used to notify the promise once it is complete - */ - public DefaultPromise(EventExecutor executor) { - if (executor == null) { - throw new NullPointerException("executor"); - } - this.executor = executor; - } - - protected DefaultPromise() { - // only for subclasses - executor = null; - } - - protected EventExecutor executor() { - return executor; - } - - @Override - public boolean isCancelled() { - return isCancelled0(result); - } - - private static boolean isCancelled0(Object result) { - return result instanceof CauseHolder && ((CauseHolder) result).cause instanceof CancellationException; - } - - @Override - public boolean isCancellable() { - return result == null; - } - - @Override - public boolean isDone() { - return isDone0(result); - } - - private static boolean isDone0(Object result) { - return result != null && result != UNCANCELLABLE; - } - - @Override - public boolean isSuccess() { - Object result = this.result; - if (result == null || result == UNCANCELLABLE) { - return false; - } - return !(result instanceof CauseHolder); - } - - @Override - public Throwable cause() { - Object result = this.result; - if (result instanceof CauseHolder) { - return ((CauseHolder) result).cause; - } - return null; - } - - @Override - public Promise addListener(GenericFutureListener> listener) { - if (listener == null) { - throw new NullPointerException("listener"); - } - - if (isDone()) { - notifyLateListener(listener); - return this; - } - - synchronized (this) { - if (!isDone()) { - if (listeners == null) { - listeners = listener; - } else { - if (listeners instanceof DefaultFutureListeners) { - ((DefaultFutureListeners) listeners).add(listener); - } else { - final GenericFutureListener> firstListener = - (GenericFutureListener>) listeners; - listeners = new DefaultFutureListeners(firstListener, listener); - } - } - return this; - } - } - - notifyLateListener(listener); - return this; - } - - @Override - public Promise addListeners(GenericFutureListener>... listeners) { - if (listeners == null) { - throw new NullPointerException("listeners"); - } - - for (GenericFutureListener> l: listeners) { - if (l == null) { - break; - } - addListener(l); - } - return this; - } - - @Override - public Promise removeListener(GenericFutureListener> listener) { - if (listener == null) { - throw new NullPointerException("listener"); - } - - if (isDone()) { - return this; - } - - synchronized (this) { - if (!isDone()) { - if (listeners instanceof DefaultFutureListeners) { - ((DefaultFutureListeners) listeners).remove(listener); - } else if (listeners == listener) { - listeners = null; - } - } - } - - return this; - } - - @Override - public Promise removeListeners(GenericFutureListener>... listeners) { - if (listeners == null) { - throw new NullPointerException("listeners"); - } - - for (GenericFutureListener> l: listeners) { - if (l == null) { - break; - } - removeListener(l); - } - return this; - } - - @Override - public Promise sync() throws InterruptedException { - await(); - rethrowIfFailed(); - return this; - } - - @Override - public Promise syncUninterruptibly() { - awaitUninterruptibly(); - rethrowIfFailed(); - return this; - } - - private void rethrowIfFailed() { - Throwable cause = cause(); - if (cause == null) { - return; - } - - PlatformDependent.throwException(cause); - } - - @Override - public Promise await() throws InterruptedException { - if (isDone()) { - return this; - } - - if (Thread.interrupted()) { - throw new InterruptedException(toString()); - } - - synchronized (this) { - while (!isDone()) { - checkDeadLock(); - incWaiters(); - try { - wait(); - } finally { - decWaiters(); - } - } - } - return this; - } - - @Override - public boolean await(long timeout, TimeUnit unit) - throws InterruptedException { - return await0(unit.toNanos(timeout), true); - } - - @Override - public boolean await(long timeoutMillis) throws InterruptedException { - return await0(MILLISECONDS.toNanos(timeoutMillis), true); - } - - @Override - public Promise awaitUninterruptibly() { - if (isDone()) { - return this; - } - - boolean interrupted = false; - synchronized (this) { - while (!isDone()) { - checkDeadLock(); - incWaiters(); - try { - wait(); - } catch (InterruptedException e) { - // Interrupted while waiting. - interrupted = true; - } finally { - decWaiters(); - } - } - } - - if (interrupted) { - Thread.currentThread().interrupt(); - } - - return this; - } - - @Override - public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - try { - return await0(unit.toNanos(timeout), false); - } catch (InterruptedException e) { - // Should not be raised at all. - throw new InternalError(); - } - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - try { - return await0(MILLISECONDS.toNanos(timeoutMillis), false); - } catch (InterruptedException e) { - // Should not be raised at all. - throw new InternalError(); - } - } - - private boolean await0(long timeoutNanos, boolean interruptable) throws InterruptedException { - if (isDone()) { - return true; - } - - if (timeoutNanos <= 0) { - return isDone(); - } - - if (interruptable && Thread.interrupted()) { - throw new InterruptedException(toString()); - } - - long startTime = System.nanoTime(); - long waitTime = timeoutNanos; - boolean interrupted = false; - - try { - synchronized (this) { - if (isDone()) { - return true; - } - - if (waitTime <= 0) { - return isDone(); - } - - checkDeadLock(); - incWaiters(); - try { - for (;;) { - try { - wait(waitTime / 1000000, (int) (waitTime % 1000000)); - } catch (InterruptedException e) { - if (interruptable) { - throw e; - } else { - interrupted = true; - } - } - - if (isDone()) { - return true; - } else { - waitTime = timeoutNanos - (System.nanoTime() - startTime); - if (waitTime <= 0) { - return isDone(); - } - } - } - } finally { - decWaiters(); - } - } - } finally { - if (interrupted) { - Thread.currentThread().interrupt(); - } - } - } - - /** - * Do deadlock checks - */ - protected void checkDeadLock() { - EventExecutor e = executor(); - if (e != null && e.inEventLoop()) { - throw new BlockingOperationException(toString()); - } - } - - @Override - public Promise setSuccess(V result) { - if (setSuccess0(result)) { - notifyListeners(); - return this; - } - throw new IllegalStateException("complete already: " + this); - } - - @Override - public boolean trySuccess(V result) { - if (setSuccess0(result)) { - notifyListeners(); - return true; - } - return false; - } - - @Override - public Promise setFailure(Throwable cause) { - if (setFailure0(cause)) { - notifyListeners(); - return this; - } - throw new IllegalStateException("complete already: " + this, cause); - } - - @Override - public boolean tryFailure(Throwable cause) { - if (setFailure0(cause)) { - notifyListeners(); - return true; - } - return false; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - Object result = this.result; - if (isDone0(result) || result == UNCANCELLABLE) { - return false; - } - - synchronized (this) { - // Allow only once. - result = this.result; - if (isDone0(result) || result == UNCANCELLABLE) { - return false; - } - - this.result = CANCELLATION_CAUSE_HOLDER; - if (hasWaiters()) { - notifyAll(); - } - } - - notifyListeners(); - return true; - } - - @Override - public boolean setUncancellable() { - Object result = this.result; - if (isDone0(result)) { - return !isCancelled0(result); - } - - synchronized (this) { - // Allow only once. - result = this.result; - if (isDone0(result)) { - return !isCancelled0(result); - } - - this.result = UNCANCELLABLE; - } - return true; - } - - private boolean setFailure0(Throwable cause) { - if (cause == null) { - throw new NullPointerException("cause"); - } - - if (isDone()) { - return false; - } - - synchronized (this) { - // Allow only once. - if (isDone()) { - return false; - } - - result = new CauseHolder(cause); - if (hasWaiters()) { - notifyAll(); - } - } - return true; - } - - private boolean setSuccess0(V result) { - if (isDone()) { - return false; - } - - synchronized (this) { - // Allow only once. - if (isDone()) { - return false; - } - if (result == null) { - this.result = SUCCESS; - } else { - this.result = result; - } - if (hasWaiters()) { - notifyAll(); - } - } - return true; - } - - @Override - - public V getNow() { - Object result = this.result; - if (result instanceof CauseHolder || result == SUCCESS) { - return null; - } - return (V) result; - } - - private boolean hasWaiters() { - return waiters > 0; - } - - private void incWaiters() { - if (waiters == Short.MAX_VALUE) { - throw new IllegalStateException("too many waiters: " + this); - } - waiters ++; - } - - private void decWaiters() { - waiters --; - } - - private void notifyListeners() { - // This method doesn't need synchronization because: - // 1) This method is always called after synchronized (this) block. - // Hence any listener list modification happens-before this method. - // 2) This method is called only when 'done' is true. Once 'done' - // becomes true, the listener list is never modified - see add/removeListener() - - Object listeners = this.listeners; - if (listeners == null) { - return; - } - - EventExecutor executor = executor(); - if (executor.inEventLoop()) { - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final int stackDepth = threadLocals.futureListenerStackDepth(); - if (stackDepth < MAX_LISTENER_STACK_DEPTH) { - threadLocals.setFutureListenerStackDepth(stackDepth + 1); - try { - if (listeners instanceof DefaultFutureListeners) { - notifyListeners0(this, (DefaultFutureListeners) listeners); - } else { - final GenericFutureListener> l = - (GenericFutureListener>) listeners; - notifyListener0(this, l); - } - } finally { - this.listeners = null; - threadLocals.setFutureListenerStackDepth(stackDepth); - } - return; - } - } - - if (listeners instanceof DefaultFutureListeners) { - final DefaultFutureListeners dfl = (DefaultFutureListeners) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyListeners0(DefaultPromise.this, dfl); - DefaultPromise.this.listeners = null; - } - }); - } else { - final GenericFutureListener> l = - (GenericFutureListener>) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyListener0(DefaultPromise.this, l); - DefaultPromise.this.listeners = null; - } - }); - } - } - - private static void notifyListeners0(Future future, DefaultFutureListeners listeners) { - final GenericFutureListener[] a = listeners.listeners(); - final int size = listeners.size(); - for (int i = 0; i < size; i ++) { - notifyListener0(future, a[i]); - } - } - - /** - * Notifies the specified listener which were added after this promise is already done. - * This method ensures that the specified listener is not notified until {@link #listeners} becomes {@code null} - * to avoid the case where the late listeners are notified even before the early listeners are notified. - */ - private void notifyLateListener(final GenericFutureListener l) { - final EventExecutor executor = executor(); - if (executor.inEventLoop()) { - if (listeners == null && lateListeners == null) { - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final int stackDepth = threadLocals.futureListenerStackDepth(); - if (stackDepth < MAX_LISTENER_STACK_DEPTH) { - threadLocals.setFutureListenerStackDepth(stackDepth + 1); - try { - notifyListener0(this, l); - } finally { - threadLocals.setFutureListenerStackDepth(stackDepth); - } - return; - } - } else { - LateListeners lateListeners = this.lateListeners; - if (lateListeners == null) { - this.lateListeners = lateListeners = new LateListeners(); - } - lateListeners.add(l); - execute(executor, lateListeners); - return; - } - } - - // Add the late listener to lateListeners in the executor thread for thread safety. - // We could just make LateListeners extend ConcurrentLinkedQueue, but it's an overkill considering - // that most asynchronous applications won't execute this code path. - execute(executor, new LateListenerNotifier(l)); - } - - protected static void notifyListener( - final EventExecutor eventExecutor, final Future future, final GenericFutureListener l) { - - if (eventExecutor.inEventLoop()) { - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final int stackDepth = threadLocals.futureListenerStackDepth(); - if (stackDepth < MAX_LISTENER_STACK_DEPTH) { - threadLocals.setFutureListenerStackDepth(stackDepth + 1); - try { - notifyListener0(future, l); - } finally { - threadLocals.setFutureListenerStackDepth(stackDepth); - } - return; - } - } - - execute(eventExecutor, new Runnable() { - @Override - public void run() { - notifyListener0(future, l); - } - }); - } - - private static void execute(EventExecutor executor, Runnable task) { - try { - executor.execute(task); - } catch (Throwable t) { - rejectedExecutionLogger.error("Failed to submit a listener notification task. Event loop shut down?", t); - } - } - - - static void notifyListener0(Future future, GenericFutureListener l) { - try { - l.operationComplete(future); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("An exception was thrown by " + l.getClass().getName() + ".operationComplete()", t); - } - } - } - - /** - * Returns a {@link GenericProgressiveFutureListener}, an array of {@link GenericProgressiveFutureListener}, or - * {@code null}. - */ - private synchronized Object progressiveListeners() { - Object listeners = this.listeners; - if (listeners == null) { - // No listeners added - return null; - } - - if (listeners instanceof DefaultFutureListeners) { - // Copy DefaultFutureListeners into an array of listeners. - DefaultFutureListeners dfl = (DefaultFutureListeners) listeners; - int progressiveSize = dfl.progressiveSize(); - switch (progressiveSize) { - case 0: - return null; - case 1: - for (GenericFutureListener l: dfl.listeners()) { - if (l instanceof GenericProgressiveFutureListener) { - return l; - } - } - return null; - } - - GenericFutureListener[] array = dfl.listeners(); - GenericProgressiveFutureListener[] copy = new GenericProgressiveFutureListener[progressiveSize]; - for (int i = 0, j = 0; j < progressiveSize; i ++) { - GenericFutureListener l = array[i]; - if (l instanceof GenericProgressiveFutureListener) { - copy[j ++] = (GenericProgressiveFutureListener) l; - } - } - - return copy; - } else if (listeners instanceof GenericProgressiveFutureListener) { - return listeners; - } else { - // Only one listener was added and it's not a progressive listener. - return null; - } - } - - - void notifyProgressiveListeners(final long progress, final long total) { - final Object listeners = progressiveListeners(); - if (listeners == null) { - return; - } - - final ProgressiveFuture self = (ProgressiveFuture) this; - - EventExecutor executor = executor(); - if (executor.inEventLoop()) { - if (listeners instanceof GenericProgressiveFutureListener[]) { - notifyProgressiveListeners0( - self, (GenericProgressiveFutureListener[]) listeners, progress, total); - } else { - notifyProgressiveListener0( - self, (GenericProgressiveFutureListener>) listeners, progress, total); - } - } else { - if (listeners instanceof GenericProgressiveFutureListener[]) { - final GenericProgressiveFutureListener[] array = - (GenericProgressiveFutureListener[]) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyProgressiveListeners0(self, array, progress, total); - } - }); - } else { - final GenericProgressiveFutureListener> l = - (GenericProgressiveFutureListener>) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyProgressiveListener0(self, l, progress, total); - } - }); - } - } - } - - private static void notifyProgressiveListeners0( - ProgressiveFuture future, GenericProgressiveFutureListener[] listeners, long progress, long total) { - for (GenericProgressiveFutureListener l: listeners) { - if (l == null) { - break; - } - notifyProgressiveListener0(future, l, progress, total); - } - } - - - private static void notifyProgressiveListener0( - ProgressiveFuture future, GenericProgressiveFutureListener l, long progress, long total) { - try { - l.operationProgressed(future, progress, total); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("An exception was thrown by " + l.getClass().getName() + ".operationProgressed()", t); - } - } - } - - private static final class CauseHolder { - final Throwable cause; - CauseHolder(Throwable cause) { - this.cause = cause; - } - } - - @Override - public String toString() { - return toStringBuilder().toString(); - } - - protected StringBuilder toStringBuilder() { - StringBuilder buf = new StringBuilder(64); - buf.append(StringUtil.simpleClassName(this)); - buf.append('@'); - buf.append(Integer.toHexString(hashCode())); - - Object result = this.result; - if (result == SUCCESS) { - buf.append("(success)"); - } else if (result == UNCANCELLABLE) { - buf.append("(uncancellable)"); - } else if (result instanceof CauseHolder) { - buf.append("(failure("); - buf.append(((CauseHolder) result).cause); - buf.append(')'); - } else { - buf.append("(incomplete)"); - } - return buf; - } - - private final class LateListeners extends ArrayDeque> implements Runnable { - - private static final long serialVersionUID = -687137418080392244L; - - LateListeners() { - super(2); - } - - @Override - public void run() { - if (listeners == null) { - for (;;) { - GenericFutureListener l = poll(); - if (l == null) { - break; - } - notifyListener0(DefaultPromise.this, l); - } - } else { - // Reschedule until the initial notification is done to avoid the race condition - // where the notification is made in an incorrect order. - execute(executor(), this); - } - } - } - - private final class LateListenerNotifier implements Runnable { - private GenericFutureListener l; - - LateListenerNotifier(GenericFutureListener l) { - this.l = l; - } - - @Override - public void run() { - LateListeners lateListeners = DefaultPromise.this.lateListeners; - if (l != null) { - if (lateListeners == null) { - DefaultPromise.this.lateListeners = lateListeners = new LateListeners(); - } - lateListeners.add(l); - l = null; - } - - lateListeners.run(); - } - } -} diff --git a/java/src/game/net/util/concurrent/DefaultThreadFactory.java b/java/src/game/net/util/concurrent/DefaultThreadFactory.java deleted file mode 100644 index bde2e42..0000000 --- a/java/src/game/net/util/concurrent/DefaultThreadFactory.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.concurrent; - -import java.util.Locale; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -import game.net.util.internal.StringUtil; - -/** - * A {@link ThreadFactory} implementation with a simple naming rule. - */ -public class DefaultThreadFactory implements ThreadFactory { - - private static final AtomicInteger poolId = new AtomicInteger(); - - private final AtomicInteger nextId = new AtomicInteger(); - private final String prefix; - private final boolean daemon; - private final int priority; - - public DefaultThreadFactory(Class poolType) { - this(poolType, false, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(String poolName) { - this(poolName, false, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(Class poolType, boolean daemon) { - this(poolType, daemon, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(String poolName, boolean daemon) { - this(poolName, daemon, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(Class poolType, int priority) { - this(poolType, false, priority); - } - - public DefaultThreadFactory(String poolName, int priority) { - this(poolName, false, priority); - } - - public DefaultThreadFactory(Class poolType, boolean daemon, int priority) { - this(toPoolName(poolType), daemon, priority); - } - - private static String toPoolName(Class poolType) { - if (poolType == null) { - throw new NullPointerException("poolType"); - } - - String poolName = StringUtil.simpleClassName(poolType); - switch (poolName.length()) { - case 0: - return "unknown"; - case 1: - return poolName.toLowerCase(Locale.US); - default: - if (Character.isUpperCase(poolName.charAt(0)) && Character.isLowerCase(poolName.charAt(1))) { - return Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1); - } else { - return poolName; - } - } - } - - public DefaultThreadFactory(String poolName, boolean daemon, int priority) { - if (poolName == null) { - throw new NullPointerException("poolName"); - } - if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { - throw new IllegalArgumentException( - "priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)"); - } - - prefix = poolName + '-' + poolId.incrementAndGet() + '-'; - this.daemon = daemon; - this.priority = priority; - } - - @Override - public Thread newThread(Runnable r) { - Thread t = newThread(new DefaultRunnableDecorator(r), prefix + nextId.incrementAndGet()); - try { - if (t.isDaemon()) { - if (!daemon) { - t.setDaemon(false); - } - } else { - if (daemon) { - t.setDaemon(true); - } - } - - if (t.getPriority() != priority) { - t.setPriority(priority); - } - } catch (Exception ignored) { - // Doesn't matter even if failed to set. - } - return t; - } - - protected Thread newThread(Runnable r, String name) { - return new FastThreadLocalThread(r, name); - } - - private static final class DefaultRunnableDecorator implements Runnable { - - private final Runnable r; - - DefaultRunnableDecorator(Runnable r) { - this.r = r; - } - - @Override - public void run() { - try { - r.run(); - } finally { - FastThreadLocal.removeAll(); - } - } - } -} diff --git a/java/src/game/net/util/concurrent/EventExecutor.java b/java/src/game/net/util/concurrent/EventExecutor.java deleted file mode 100644 index 5faa3d6..0000000 --- a/java/src/game/net/util/concurrent/EventExecutor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -/** - * The {@link EventExecutor} is a special {@link EventExecutorGroup} which comes - * with some handy methods to see if a {@link Thread} is executed in a event loop. - * Beside this it also extends the {@link EventExecutorGroup} to allow a generic way to - * access methods. - * - */ -public interface EventExecutor extends EventExecutorGroup { - - /** - * Returns a reference to itself. - */ - @Override - EventExecutor next(); - - /** - * Return the {@link EventExecutorGroup} which is the parent of this {@link EventExecutor}, - */ - EventExecutorGroup parent(); - - /** - * Calls {@link #inEventLoop(Thread)} with {@link Thread#currentThread()} as argument - */ - boolean inEventLoop(); - - /** - * Return {@code true} if the given {@link Thread} is executed in the event loop, - * {@code false} otherwise. - */ - boolean inEventLoop(Thread thread); - - /** - * Return a new {@link Promise}. - */ - Promise newPromise(); - - /** - * Create a new {@link ProgressivePromise}. - */ - ProgressivePromise newProgressivePromise(); - - /** - * Create a new {@link Future} which is marked as successes already. So {@link Future#isSuccess()} - * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - Future newSucceededFuture(V result); - - /** - * Create a new {@link Future} which is marked as fakued already. So {@link Future#isSuccess()} - * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - Future newFailedFuture(Throwable cause); -} diff --git a/java/src/game/net/util/concurrent/EventExecutorGroup.java b/java/src/game/net/util/concurrent/EventExecutorGroup.java deleted file mode 100644 index 32668a6..0000000 --- a/java/src/game/net/util/concurrent/EventExecutorGroup.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * The {@link EventExecutorGroup} is responsible to provide {@link EventExecutor}'s to use via its - * {@link #next()} method. Beside this it also is responsible to handle their live-cycle and allows - * to shut them down in a global fashion. - * - */ -public interface EventExecutorGroup extends ScheduledExecutorService, Iterable { - - /** - * Returns {@code true} if and only if this executor was started to be - * {@linkplain #shutdownGracefully() shut down gracefuclly} or was {@linkplain #isShutdown() shut down}. - */ - boolean isShuttingDown(); - - /** - * Shortcut method for {@link #shutdownGracefully(long, long, TimeUnit)} with sensible default values. - * - * @return the {@link #terminationFuture()} - */ - Future shutdownGracefully(); - - /** - * Signals this executor that the caller wants the executor to be shut down. Once this method is called, - * {@link #isShuttingDown()} starts to return {@code true}, and the executor prepares to shut itself down. - * Unlike {@link #shutdown()}, graceful shutdown ensures that no tasks are submitted for 'the quiet period' - * (usually a couple seconds) before it shuts itself down. If a task is submitted during the quiet period, - * it is guaranteed to be accepted and the quiet period will start over. - * - * @param quietPeriod the quiet period as described in the documentation - * @param timeout the maximum amount of time to wait until the executor is {@linkplain #shutdown()} - * regardless if a task was submitted during the quiet period - * @param unit the unit of {@code quietPeriod} and {@code timeout} - * - * @return the {@link #terminationFuture()} - */ - Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit); - - /** - * Returns the {@link Future} which is notified when this executor has been terminated. - */ - Future terminationFuture(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - void shutdown(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - List shutdownNow(); - - /** - * Returns one of the {@link EventExecutor}s that belong to this group. - */ - EventExecutor next(); - - /** - * Returns a read-only {@link Iterator} over all {@link EventExecutor}, which are handled by this - * {@link EventExecutorGroup} at the time of invoke this method. - */ - @Override - Iterator iterator(); - - @Override - Future submit(Runnable task); - - @Override - Future submit(Runnable task, T result); - - @Override - Future submit(Callable task); - - @Override - ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit); - - @Override - ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit); - - @Override - ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); - - @Override - ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); -} diff --git a/java/src/game/net/util/concurrent/FailedFuture.java b/java/src/game/net/util/concurrent/FailedFuture.java deleted file mode 100644 index 330d5a7..0000000 --- a/java/src/game/net/util/concurrent/FailedFuture.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import game.net.util.internal.PlatformDependent; - -/** - * The {@link CompleteFuture} which is failed already. It is - * recommended to use {@link EventExecutor#newFailedFuture(Throwable)} - * instead of calling the constructor of this future. - */ -public final class FailedFuture extends CompleteFuture { - - private final Throwable cause; - - /** - * Creates a new instance. - * - * @param executor the {@link EventExecutor} associated with this future - * @param cause the cause of failure - */ - public FailedFuture(EventExecutor executor, Throwable cause) { - super(executor); - if (cause == null) { - throw new NullPointerException("cause"); - } - this.cause = cause; - } - - @Override - public Throwable cause() { - return cause; - } - - @Override - public boolean isSuccess() { - return false; - } - - @Override - public Future sync() { - PlatformDependent.throwException(cause); - return this; - } - - @Override - public Future syncUninterruptibly() { - PlatformDependent.throwException(cause); - return this; - } - - @Override - public V getNow() { - return null; - } -} diff --git a/java/src/game/net/util/concurrent/FastThreadLocal.java b/java/src/game/net/util/concurrent/FastThreadLocal.java deleted file mode 100644 index 0091d77..0000000 --- a/java/src/game/net/util/concurrent/FastThreadLocal.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.Set; - -import game.net.util.internal.InternalThreadLocalMap; -import game.net.util.internal.PlatformDependent; - -/** - * A special variant of {@link ThreadLocal} that yields higher access performan when accessed from a - * {@link FastThreadLocalThread}. - *

- * Internally, a {@link FastThreadLocal} uses a constant index in an array, instead of using hash code and hash table, - * to look for a variable. Although seemingly very subtle, it yields slight performance advantage over using a hash - * table, and it is useful when accessed frequently. - *

- * To take advantage of this thread-local variable, your thread must be a {@link FastThreadLocalThread} or its subtype. - * By default, all threads created by {@link DefaultThreadFactory} are {@link FastThreadLocalThread} due to this reason. - *

- * Note that the fast path is only possible on threads that extend {@link FastThreadLocalThread}, because it requires - * a special field to store the necessary state. An access by any other kind of thread falls back to a regular - * {@link ThreadLocal}. - *

- * - * @param the type of the thread-local variable - * @see ThreadLocal - */ -public class FastThreadLocal { - - private static final int variablesToRemoveIndex = InternalThreadLocalMap.nextVariableIndex(); - - /** - * Removes all {@link FastThreadLocal} variables bound to the current thread. This operation is useful when you - * are in a container environment, and you don't want to leave the thread local variables in the threads you do not - * manage. - */ - public static void removeAll() { - InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet(); - if (threadLocalMap == null) { - return; - } - - try { - Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex); - if (v != null && v != InternalThreadLocalMap.UNSET) { - - Set> variablesToRemove = (Set>) v; - FastThreadLocal[] variablesToRemoveArray = - variablesToRemove.toArray(new FastThreadLocal[variablesToRemove.size()]); - for (FastThreadLocal tlv: variablesToRemoveArray) { - tlv.remove(threadLocalMap); - } - } - } finally { - InternalThreadLocalMap.remove(); - } - } - - /** - * Returns the number of thread local variables bound to the current thread. - */ - public static int size() { - InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet(); - if (threadLocalMap == null) { - return 0; - } else { - return threadLocalMap.size(); - } - } - - /** - * Destroys the data structure that keeps all {@link FastThreadLocal} variables accessed from - * non-{@link FastThreadLocalThread}s. This operation is useful when you are in a container environment, and you - * do not want to leave the thread local variables in the threads you do not manage. Call this method when your - * application is being unloaded from the container. - */ - public static void destroy() { - InternalThreadLocalMap.destroy(); - } - - - private static void addToVariablesToRemove(InternalThreadLocalMap threadLocalMap, FastThreadLocal variable) { - Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex); - Set> variablesToRemove; - if (v == InternalThreadLocalMap.UNSET || v == null) { - variablesToRemove = Collections.newSetFromMap(new IdentityHashMap, Boolean>()); - threadLocalMap.setIndexedVariable(variablesToRemoveIndex, variablesToRemove); - } else { - variablesToRemove = (Set>) v; - } - - variablesToRemove.add(variable); - } - - private static void removeFromVariablesToRemove( - InternalThreadLocalMap threadLocalMap, FastThreadLocal variable) { - - Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex); - - if (v == InternalThreadLocalMap.UNSET || v == null) { - return; - } - - - Set> variablesToRemove = (Set>) v; - variablesToRemove.remove(variable); - } - - private final int index; - - public FastThreadLocal() { - index = InternalThreadLocalMap.nextVariableIndex(); - } - - /** - * Returns the current value for the current thread - */ - public final V get() { - return get(InternalThreadLocalMap.get()); - } - - /** - * Returns the current value for the specified thread local map. - * The specified thread local map must be for the current thread. - */ - - public final V get(InternalThreadLocalMap threadLocalMap) { - Object v = threadLocalMap.indexedVariable(index); - if (v != InternalThreadLocalMap.UNSET) { - return (V) v; - } - - return initialize(threadLocalMap); - } - - private V initialize(InternalThreadLocalMap threadLocalMap) { - V v = null; - try { - v = initialValue(); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - - threadLocalMap.setIndexedVariable(index, v); - addToVariablesToRemove(threadLocalMap, this); - return v; - } - - /** - * Set the value for the current thread. - */ - public final void set(V value) { - if (value != InternalThreadLocalMap.UNSET) { - set(InternalThreadLocalMap.get(), value); - } else { - remove(); - } - } - - /** - * Set the value for the specified thread local map. The specified thread local map must be for the current thread. - */ - public final void set(InternalThreadLocalMap threadLocalMap, V value) { - if (value != InternalThreadLocalMap.UNSET) { - if (threadLocalMap.setIndexedVariable(index, value)) { - addToVariablesToRemove(threadLocalMap, this); - } - } else { - remove(threadLocalMap); - } - } - - /** - * Returns {@code true} if and only if this thread-local variable is set. - */ - public final boolean isSet() { - return isSet(InternalThreadLocalMap.getIfSet()); - } - - /** - * Returns {@code true} if and only if this thread-local variable is set. - * The specified thread local map must be for the current thread. - */ - public final boolean isSet(InternalThreadLocalMap threadLocalMap) { - return threadLocalMap != null && threadLocalMap.isIndexedVariableSet(index); - } - /** - * Sets the value to uninitialized; a proceeding call to get() will trigger a call to initialValue(). - */ - public final void remove() { - remove(InternalThreadLocalMap.getIfSet()); - } - - /** - * Sets the value to uninitialized for the specified thread local map; - * a proceeding call to get() will trigger a call to initialValue(). - * The specified thread local map must be for the current thread. - */ - - public final void remove(InternalThreadLocalMap threadLocalMap) { - if (threadLocalMap == null) { - return; - } - - Object v = threadLocalMap.removeIndexedVariable(index); - removeFromVariablesToRemove(threadLocalMap, this); - - if (v != InternalThreadLocalMap.UNSET) { - try { - onRemoval((V) v); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - } - } - - /** - * Returns the initial value for this thread-local variable. - */ - protected V initialValue() throws Exception { - return null; - } - - /** - * Invoked when this thread local variable is removed by {@link #remove()}. - */ - protected void onRemoval( V value) throws Exception { } -} diff --git a/java/src/game/net/util/concurrent/FastThreadLocalThread.java b/java/src/game/net/util/concurrent/FastThreadLocalThread.java deleted file mode 100644 index 29deabd..0000000 --- a/java/src/game/net/util/concurrent/FastThreadLocalThread.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ -package game.net.util.concurrent; - -import game.net.util.internal.InternalThreadLocalMap; - -/** - * A special {@link Thread} that provides fast access to {@link FastThreadLocal} variables. - */ -public class FastThreadLocalThread extends Thread { - - private InternalThreadLocalMap threadLocalMap; - - public FastThreadLocalThread() { } - - public FastThreadLocalThread(Runnable target) { - super(target); - } - - public FastThreadLocalThread(ThreadGroup group, Runnable target) { - super(group, target); - } - - public FastThreadLocalThread(String name) { - super(name); - } - - public FastThreadLocalThread(ThreadGroup group, String name) { - super(group, name); - } - - public FastThreadLocalThread(Runnable target, String name) { - super(target, name); - } - - public FastThreadLocalThread(ThreadGroup group, Runnable target, String name) { - super(group, target, name); - } - - public FastThreadLocalThread(ThreadGroup group, Runnable target, String name, long stackSize) { - super(group, target, name, stackSize); - } - - /** - * Returns the internal data structure that keeps the thread-local variables bound to this thread. - * Note that this method is for internal use only, and thus is subject to change at any time. - */ - public final InternalThreadLocalMap threadLocalMap() { - return threadLocalMap; - } - - /** - * Sets the internal data structure that keeps the thread-local variables bound to this thread. - * Note that this method is for internal use only, and thus is subject to change at any time. - */ - public final void setThreadLocalMap(InternalThreadLocalMap threadLocalMap) { - this.threadLocalMap = threadLocalMap; - } -} diff --git a/java/src/game/net/util/concurrent/Future.java b/java/src/game/net/util/concurrent/Future.java deleted file mode 100644 index 330364a..0000000 --- a/java/src/game/net/util/concurrent/Future.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.concurrent.TimeUnit; - - -/** - * The result of an asynchronous operation. - */ - -public interface Future extends java.util.concurrent.Future { - - /** - * Returns {@code true} if and only if the I/O operation was completed - * successfully. - */ - boolean isSuccess(); - - /** - * returns {@code true} if and only if the operation can be cancelled via {@link #cancel(boolean)}. - */ - boolean isCancellable(); - - /** - * Returns the cause of the failed I/O operation if the I/O operation has - * failed. - * - * @return the cause of the failure. - * {@code null} if succeeded or this future is not - * completed yet. - */ - Throwable cause(); - - /** - * Adds the specified listener to this future. The - * specified listener is notified when this future is - * {@linkplain #isDone() done}. If this future is already - * completed, the specified listener is notified immediately. - */ - Future addListener(GenericFutureListener> listener); - - /** - * Adds the specified listeners to this future. The - * specified listeners are notified when this future is - * {@linkplain #isDone() done}. If this future is already - * completed, the specified listeners are notified immediately. - */ - Future addListeners(GenericFutureListener>... listeners); - - /** - * Removes the specified listener from this future. - * The specified listener is no longer notified when this - * future is {@linkplain #isDone() done}. If the specified - * listener is not associated with this future, this method - * does nothing and returns silently. - */ - Future removeListener(GenericFutureListener> listener); - - /** - * Removes the specified listeners from this future. - * The specified listeners are no longer notified when this - * future is {@linkplain #isDone() done}. If the specified - * listeners are not associated with this future, this method - * does nothing and returns silently. - */ - Future removeListeners(GenericFutureListener>... listeners); - - /** - * Waits for this future until it is done, and rethrows the cause of the failure if this future - * failed. - */ - Future sync() throws InterruptedException; - - /** - * Waits for this future until it is done, and rethrows the cause of the failure if this future - * failed. - */ - Future syncUninterruptibly(); - - /** - * Waits for this future to be completed. - * - * @throws InterruptedException - * if the current thread was interrupted - */ - Future await() throws InterruptedException; - - /** - * Waits for this future to be completed without - * interruption. This method catches an {@link InterruptedException} and - * discards it silently. - */ - Future awaitUninterruptibly(); - - /** - * Waits for this future to be completed within the - * specified time limit. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - * - * @throws InterruptedException - * if the current thread was interrupted - */ - boolean await(long timeout, TimeUnit unit) throws InterruptedException; - - /** - * Waits for this future to be completed within the - * specified time limit. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - * - * @throws InterruptedException - * if the current thread was interrupted - */ - boolean await(long timeoutMillis) throws InterruptedException; - - /** - * Waits for this future to be completed within the - * specified time limit without interruption. This method catches an - * {@link InterruptedException} and discards it silently. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - */ - boolean awaitUninterruptibly(long timeout, TimeUnit unit); - - /** - * Waits for this future to be completed within the - * specified time limit without interruption. This method catches an - * {@link InterruptedException} and discards it silently. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - */ - boolean awaitUninterruptibly(long timeoutMillis); - - /** - * Return the result without blocking. If the future is not done yet this will return {@code null}. - * - * As it is possible that a {@code null} value is used to mark the future as successful you also need to check - * if the future is really done with {@link #isDone()} and not relay on the returned {@code null} value. - */ - V getNow(); - - /** - * {@inheritDoc} - * - * If the cancellation was successful it will fail the future with an {@link CancellationException}. - */ - @Override - boolean cancel(boolean mayInterruptIfRunning); -} diff --git a/java/src/game/net/util/concurrent/FutureListener.java b/java/src/game/net/util/concurrent/FutureListener.java deleted file mode 100644 index b5d406c..0000000 --- a/java/src/game/net/util/concurrent/FutureListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.concurrent; - -/** - * A subtype of {@link GenericFutureListener} that hides type parameter for convenience. - *
- * Future f = new DefaultPromise(..);
- * f.addListener(new FutureListener() {
- *     public void operationComplete(Future f) { .. }
- * });
- * 
- */ -public interface FutureListener extends GenericFutureListener> { } diff --git a/java/src/game/net/util/concurrent/GenericFutureListener.java b/java/src/game/net/util/concurrent/GenericFutureListener.java deleted file mode 100644 index 472a528..0000000 --- a/java/src/game/net/util/concurrent/GenericFutureListener.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.EventListener; - -/** - * Listens to the result of a {@link Future}. The result of the asynchronous operation is notified once this listener - * is added by calling {@link Future#addListener(GenericFutureListener)}. - */ -public interface GenericFutureListener> extends EventListener { - - /** - * Invoked when the operation associated with the {@link Future} has been completed. - * - * @param future the source {@link Future} which called this callback - */ - void operationComplete(F future) throws Exception; -} diff --git a/java/src/game/net/util/concurrent/GenericProgressiveFutureListener.java b/java/src/game/net/util/concurrent/GenericProgressiveFutureListener.java deleted file mode 100644 index 27892a2..0000000 --- a/java/src/game/net/util/concurrent/GenericProgressiveFutureListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.concurrent; - -public interface GenericProgressiveFutureListener> extends GenericFutureListener { - /** - * Invoked when the operation has progressed. - * - * @param progress the progress of the operation so far (cumulative) - * @param total the number that signifies the end of the operation when {@code progress} reaches at it. - * {@code -1} if the end of operation is unknown. - */ - void operationProgressed(F future, long progress, long total) throws Exception; -} diff --git a/java/src/game/net/util/concurrent/GlobalEventExecutor.java b/java/src/game/net/util/concurrent/GlobalEventExecutor.java deleted file mode 100644 index 310e51b..0000000 --- a/java/src/game/net/util/concurrent/GlobalEventExecutor.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.Iterator; -import java.util.PriorityQueue; -import java.util.Queue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Single-thread singleton {@link EventExecutor}. It starts the thread automatically and stops it when there is no - * task pending in the task queue for 1 second. Please note it is not scalable to schedule large number of tasks to - * this executor; use a dedicated executor. - */ -public final class GlobalEventExecutor extends AbstractEventExecutor { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(GlobalEventExecutor.class); - - private static final long SCHEDULE_PURGE_INTERVAL = TimeUnit.SECONDS.toNanos(1); - - public static final GlobalEventExecutor INSTANCE = new GlobalEventExecutor(); - - final BlockingQueue taskQueue = new LinkedBlockingQueue(); - final Queue> delayedTaskQueue = new PriorityQueue>(); - final ScheduledFutureTask purgeTask = new ScheduledFutureTask( - this, delayedTaskQueue, Executors.callable(new PurgeTask(), null), - ScheduledFutureTask.deadlineNanos(SCHEDULE_PURGE_INTERVAL), -SCHEDULE_PURGE_INTERVAL); - - private final ThreadFactory threadFactory = new DefaultThreadFactory(getClass()); - private final TaskRunner taskRunner = new TaskRunner(); - private final AtomicBoolean started = new AtomicBoolean(); - volatile Thread thread; - - private final Future terminationFuture = new FailedFuture(this, new UnsupportedOperationException()); - - private GlobalEventExecutor() { - delayedTaskQueue.add(purgeTask); - } - - @Override - public EventExecutorGroup parent() { - return null; - } - - /** - * Take the next {@link Runnable} from the task queue and so will block if no task is currently present. - * - * @return {@code null} if the executor thread has been interrupted or waken up. - */ - Runnable takeTask() { - BlockingQueue taskQueue = this.taskQueue; - for (;;) { - ScheduledFutureTask delayedTask = delayedTaskQueue.peek(); - if (delayedTask == null) { - Runnable task = null; - try { - task = taskQueue.take(); - } catch (InterruptedException e) { - // Ignore - } - return task; - } else { - long delayNanos = delayedTask.delayNanos(); - Runnable task; - if (delayNanos > 0) { - try { - task = taskQueue.poll(delayNanos, TimeUnit.NANOSECONDS); - } catch (InterruptedException e) { - return null; - } - } else { - task = taskQueue.poll(); - } - - if (task == null) { - fetchFromDelayedQueue(); - task = taskQueue.poll(); - } - - if (task != null) { - return task; - } - } - } - } - - private void fetchFromDelayedQueue() { - long nanoTime = 0L; - for (;;) { - ScheduledFutureTask delayedTask = delayedTaskQueue.peek(); - if (delayedTask == null) { - break; - } - - if (nanoTime == 0L) { - nanoTime = ScheduledFutureTask.nanoTime(); - } - - if (delayedTask.deadlineNanos() <= nanoTime) { - delayedTaskQueue.remove(); - taskQueue.add(delayedTask); - } else { - break; - } - } - } - - /** - * Return the number of tasks that are pending for processing. - * - * Be aware that this operation may be expensive as it depends on the internal implementation of the - * SingleThreadEventExecutor. So use it was care! - */ - public int pendingTasks() { - return taskQueue.size(); - } - - /** - * Add a task to the task queue, or throws a {@link RejectedExecutionException} if this instance was shutdown - * before. - */ - private void addTask(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - taskQueue.add(task); - } - - @Override - public boolean inEventLoop(Thread thread) { - return thread == this.thread; - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isShuttingDown() { - return false; - } - - @Override - public boolean isShutdown() { - return false; - } - - @Override - public boolean isTerminated() { - return false; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) { - return false; - } - - /** - * Waits until the worker thread of this executor has no tasks left in its task queue and terminates itself. - * Because a new worker thread will be started again when a new task is submitted, this operation is only useful - * when you want to ensure that the worker thread is terminated after your application is shut - * down and there's no chance of submitting a new task afterwards. - * - * @return {@code true} if and only if the worker thread has been terminated - */ - public boolean awaitInactivity(long timeout, TimeUnit unit) throws InterruptedException { - if (unit == null) { - throw new NullPointerException("unit"); - } - - final Thread thread = this.thread; - if (thread == null) { - throw new IllegalStateException("thread was not started"); - } - thread.join(unit.toMillis(timeout)); - return !thread.isAlive(); - } - - @Override - public void execute(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - - addTask(task); - if (!inEventLoop()) { - startThread(); - } - } - - // ScheduledExecutorService implementation - - @Override - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { - if (command == null) { - throw new NullPointerException("command"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (delay < 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: >= 0)", delay)); - } - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, command, null, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay)))); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - if (callable == null) { - throw new NullPointerException("callable"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (delay < 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: >= 0)", delay)); - } - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, callable, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay)))); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - if (command == null) { - throw new NullPointerException("command"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (initialDelay < 0) { - throw new IllegalArgumentException( - String.format("initialDelay: %d (expected: >= 0)", initialDelay)); - } - if (period <= 0) { - throw new IllegalArgumentException( - String.format("period: %d (expected: > 0)", period)); - } - - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, Executors.callable(command, null), - ScheduledFutureTask.deadlineNanos(unit.toNanos(initialDelay)), unit.toNanos(period))); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - if (command == null) { - throw new NullPointerException("command"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (initialDelay < 0) { - throw new IllegalArgumentException( - String.format("initialDelay: %d (expected: >= 0)", initialDelay)); - } - if (delay <= 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: > 0)", delay)); - } - - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, Executors.callable(command, null), - ScheduledFutureTask.deadlineNanos(unit.toNanos(initialDelay)), -unit.toNanos(delay))); - } - - private ScheduledFuture schedule(final ScheduledFutureTask task) { - if (task == null) { - throw new NullPointerException("task"); - } - - if (inEventLoop()) { - delayedTaskQueue.add(task); - } else { - execute(new Runnable() { - @Override - public void run() { - delayedTaskQueue.add(task); - } - }); - } - - return task; - } - - private void startThread() { - if (started.compareAndSet(false, true)) { - Thread t = threadFactory.newThread(taskRunner); - t.start(); - thread = t; - } - } - - final class TaskRunner implements Runnable { - @Override - public void run() { - for (;;) { - Runnable task = takeTask(); - if (task != null) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("Unexpected exception from the global event executor: ", t); - } - - if (task != purgeTask) { - continue; - } - } - - // Terminate if there is no task in the queue (except the purge task). - if (taskQueue.isEmpty() && delayedTaskQueue.size() == 1) { - // Mark the current thread as stopped. - // The following CAS must always success and must be uncontended, - // because only one thread should be running at the same time. - boolean stopped = started.compareAndSet(true, false); - assert stopped; - - // Check if there are pending entries added by execute() or schedule*() while we do CAS above. - if (taskQueue.isEmpty() && delayedTaskQueue.size() == 1) { - // A) No new task was added and thus there's nothing to handle - // -> safe to terminate because there's nothing left to do - // B) A new thread started and handled all the new tasks. - // -> safe to terminate the new thread will take care the rest - break; - } - - // There are pending tasks added again. - if (!started.compareAndSet(false, true)) { - // startThread() started a new thread and set 'started' to true. - // -> terminate this thread so that the new thread reads from taskQueue exclusively. - break; - } - - // New tasks were added, but this worker was faster to set 'started' to true. - // i.e. a new worker thread was not started by startThread(). - // -> keep this thread alive to handle the newly added entries. - } - } - } - } - - private final class PurgeTask implements Runnable { - @Override - public void run() { - Iterator> i = delayedTaskQueue.iterator(); - while (i.hasNext()) { - ScheduledFutureTask task = i.next(); - if (task.isCancelled()) { - i.remove(); - } - } - } - } -} diff --git a/java/src/game/net/util/concurrent/ImmediateEventExecutor.java b/java/src/game/net/util/concurrent/ImmediateEventExecutor.java deleted file mode 100644 index fec33e5..0000000 --- a/java/src/game/net/util/concurrent/ImmediateEventExecutor.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.concurrent.TimeUnit; - -/** - * {@link AbstractEventExecutor} which execute tasks in the callers thread. - */ -public final class ImmediateEventExecutor extends AbstractEventExecutor { - public static final ImmediateEventExecutor INSTANCE = new ImmediateEventExecutor(); - - private final Future terminationFuture = new FailedFuture( - GlobalEventExecutor.INSTANCE, new UnsupportedOperationException()); - - private ImmediateEventExecutor() { - // use static instance - } - - @Override - public EventExecutorGroup parent() { - return null; - } - - @Override - public boolean inEventLoop() { - return true; - } - - @Override - public boolean inEventLoop(Thread thread) { - return true; - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { } - - @Override - public boolean isShuttingDown() { - return false; - } - - @Override - public boolean isShutdown() { - return false; - } - - @Override - public boolean isTerminated() { - return false; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) { - return false; - } - - @Override - public void execute(Runnable command) { - if (command == null) { - throw new NullPointerException("command"); - } - command.run(); - } - - @Override - public Promise newPromise() { - return new ImmediatePromise(this); - } - - @Override - public ProgressivePromise newProgressivePromise() { - return new ImmediateProgressivePromise(this); - } - - static class ImmediatePromise extends DefaultPromise { - ImmediatePromise(EventExecutor executor) { - super(executor); - } - - @Override - protected void checkDeadLock() { - // No check - } - } - - static class ImmediateProgressivePromise extends DefaultProgressivePromise { - ImmediateProgressivePromise(EventExecutor executor) { - super(executor); - } - - @Override - protected void checkDeadLock() { - // No check - } - } -} diff --git a/java/src/game/net/util/concurrent/ImmediateExecutor.java b/java/src/game/net/util/concurrent/ImmediateExecutor.java deleted file mode 100644 index d797626..0000000 --- a/java/src/game/net/util/concurrent/ImmediateExecutor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.concurrent.Executor; - -/** - * {@link Executor} which execute tasks in the callers thread. - */ -public final class ImmediateExecutor implements Executor { - public static final ImmediateExecutor INSTANCE = new ImmediateExecutor(); - - private ImmediateExecutor() { - // use static instance - } - - @Override - public void execute(Runnable command) { - if (command == null) { - throw new NullPointerException("command"); - } - command.run(); - } -} diff --git a/java/src/game/net/util/concurrent/MultithreadEventExecutorGroup.java b/java/src/game/net/util/concurrent/MultithreadEventExecutorGroup.java deleted file mode 100644 index 0c65b60..0000000 --- a/java/src/game/net/util/concurrent/MultithreadEventExecutorGroup.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Set; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Abstract base class for {@link EventExecutorGroup} implementations that handles their tasks with multiple threads at - * the same time. - */ -public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup { - - private final EventExecutor[] children; - private final AtomicInteger childIndex = new AtomicInteger(); - private final AtomicInteger terminatedChildren = new AtomicInteger(); - private final Promise terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE); - private final EventExecutorChooser chooser; - - /** - * Create a new instance. - * - * @param nThreads the number of threads that will be used by this instance. - * @param threadFactory the ThreadFactory to use, or {@code null} if the default should be used. - * @param args arguments which will passed to each {@link #newChild(ThreadFactory, Object...)} call - */ - protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) { - if (nThreads <= 0) { - throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads)); - } - - if (threadFactory == null) { - threadFactory = newDefaultThreadFactory(); - } - - children = new SingleThreadEventExecutor[nThreads]; - if (isPowerOfTwo(children.length)) { - chooser = new PowerOfTwoEventExecutorChooser(); - } else { - chooser = new GenericEventExecutorChooser(); - } - - for (int i = 0; i < nThreads; i ++) { - boolean success = false; - try { - children[i] = newChild(threadFactory, args); - success = true; - } catch (Exception e) { - // TODO: Think about if this is a good exception type - throw new IllegalStateException("failed to create a child event loop", e); - } finally { - if (!success) { - for (int j = 0; j < i; j ++) { - children[j].shutdownGracefully(); - } - - for (int j = 0; j < i; j ++) { - EventExecutor e = children[j]; - try { - while (!e.isTerminated()) { - e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); - } - } catch (InterruptedException interrupted) { - Thread.currentThread().interrupt(); - break; - } - } - } - } - } - - final FutureListener terminationListener = new FutureListener() { - @Override - public void operationComplete(Future future) throws Exception { - if (terminatedChildren.incrementAndGet() == children.length) { - terminationFuture.setSuccess(null); - } - } - }; - - for (EventExecutor e: children) { - e.terminationFuture().addListener(terminationListener); - } - } - - protected ThreadFactory newDefaultThreadFactory() { - return new DefaultThreadFactory(getClass()); - } - - @Override - public EventExecutor next() { - return chooser.next(); - } - - @Override - public Iterator iterator() { - return children().iterator(); - } - - /** - * Return the number of {@link EventExecutor} this implementation uses. This number is the maps - * 1:1 to the threads it use. - */ - public final int executorCount() { - return children.length; - } - - /** - * Return a safe-copy of all of the children of this group. - */ - protected Set children() { - Set children = Collections.newSetFromMap(new LinkedHashMap()); - Collections.addAll(children, this.children); - return children; - } - - /** - * Create a new EventExecutor which will later then accessible via the {@link #next()} method. This method will be - * called for each thread that will serve this {@link MultithreadEventExecutorGroup}. - * - */ - protected abstract EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception; - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - for (EventExecutor l: children) { - l.shutdownGracefully(quietPeriod, timeout, unit); - } - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { - for (EventExecutor l: children) { - l.shutdown(); - } - } - - @Override - public boolean isShuttingDown() { - for (EventExecutor l: children) { - if (!l.isShuttingDown()) { - return false; - } - } - return true; - } - - @Override - public boolean isShutdown() { - for (EventExecutor l: children) { - if (!l.isShutdown()) { - return false; - } - } - return true; - } - - @Override - public boolean isTerminated() { - for (EventExecutor l: children) { - if (!l.isTerminated()) { - return false; - } - } - return true; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - long deadline = System.nanoTime() + unit.toNanos(timeout); - loop: for (EventExecutor l: children) { - for (;;) { - long timeLeft = deadline - System.nanoTime(); - if (timeLeft <= 0) { - break loop; - } - if (l.awaitTermination(timeLeft, TimeUnit.NANOSECONDS)) { - break; - } - } - } - return isTerminated(); - } - - private static boolean isPowerOfTwo(int val) { - return (val & -val) == val; - } - - private interface EventExecutorChooser { - EventExecutor next(); - } - - private final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser { - @Override - public EventExecutor next() { - return children[childIndex.getAndIncrement() & children.length - 1]; - } - } - - private final class GenericEventExecutorChooser implements EventExecutorChooser { - @Override - public EventExecutor next() { - return children[Math.abs(childIndex.getAndIncrement() % children.length)]; - } - } -} diff --git a/java/src/game/net/util/concurrent/ProgressiveFuture.java b/java/src/game/net/util/concurrent/ProgressiveFuture.java deleted file mode 100644 index 644e18c..0000000 --- a/java/src/game/net/util/concurrent/ProgressiveFuture.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.concurrent; - -/** - * A {@link Future} which is used to indicate the progress of an operation. - */ -public interface ProgressiveFuture extends Future { - - @Override - ProgressiveFuture addListener(GenericFutureListener> listener); - - @Override - ProgressiveFuture addListeners(GenericFutureListener>... listeners); - - @Override - ProgressiveFuture removeListener(GenericFutureListener> listener); - - @Override - ProgressiveFuture removeListeners(GenericFutureListener>... listeners); - - @Override - ProgressiveFuture sync() throws InterruptedException; - - @Override - ProgressiveFuture syncUninterruptibly(); - - @Override - ProgressiveFuture await() throws InterruptedException; - - @Override - ProgressiveFuture awaitUninterruptibly(); -} diff --git a/java/src/game/net/util/concurrent/ProgressivePromise.java b/java/src/game/net/util/concurrent/ProgressivePromise.java deleted file mode 100644 index 8981e48..0000000 --- a/java/src/game/net/util/concurrent/ProgressivePromise.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -/** - * Special {@link ProgressiveFuture} which is writable. - */ -public interface ProgressivePromise extends Promise, ProgressiveFuture { - - /** - * Sets the current progress of the operation and notifies the listeners that implement - * {@link GenericProgressiveFutureListener}. - */ - ProgressivePromise setProgress(long progress, long total); - - /** - * Tries to set the current progress of the operation and notifies the listeners that implement - * {@link GenericProgressiveFutureListener}. If the operation is already complete or the progress is out of range, - * this method does nothing but returning {@code false}. - */ - boolean tryProgress(long progress, long total); - - @Override - ProgressivePromise setSuccess(V result); - - @Override - ProgressivePromise setFailure(Throwable cause); - - @Override - ProgressivePromise addListener(GenericFutureListener> listener); - - @Override - ProgressivePromise addListeners(GenericFutureListener>... listeners); - - @Override - ProgressivePromise removeListener(GenericFutureListener> listener); - - @Override - ProgressivePromise removeListeners(GenericFutureListener>... listeners); - - @Override - ProgressivePromise await() throws InterruptedException; - - @Override - ProgressivePromise awaitUninterruptibly(); - - @Override - ProgressivePromise sync() throws InterruptedException; - - @Override - ProgressivePromise syncUninterruptibly(); -} diff --git a/java/src/game/net/util/concurrent/Promise.java b/java/src/game/net/util/concurrent/Promise.java deleted file mode 100644 index 191663d..0000000 --- a/java/src/game/net/util/concurrent/Promise.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -/** - * Special {@link Future} which is writable. - */ -public interface Promise extends Future { - - /** - * Marks this future as a success and notifies all - * listeners. - * - * If it is success or failed already it will throw an {@link IllegalStateException}. - */ - Promise setSuccess(V result); - - /** - * Marks this future as a success and notifies all - * listeners. - * - * @return {@code true} if and only if successfully marked this future as - * a success. Otherwise {@code false} because this future is - * already marked as either a success or a failure. - */ - boolean trySuccess(V result); - - /** - * Marks this future as a failure and notifies all - * listeners. - * - * If it is success or failed already it will throw an {@link IllegalStateException}. - */ - Promise setFailure(Throwable cause); - - /** - * Marks this future as a failure and notifies all - * listeners. - * - * @return {@code true} if and only if successfully marked this future as - * a failure. Otherwise {@code false} because this future is - * already marked as either a success or a failure. - */ - boolean tryFailure(Throwable cause); - - /** - * Make this future impossible to cancel. - * - * @return {@code true} if and only if successfully marked this future as uncancellable or it is already done - * without being cancelled. {@code false} if this future has been cancelled already. - */ - boolean setUncancellable(); - - @Override - Promise addListener(GenericFutureListener> listener); - - @Override - Promise addListeners(GenericFutureListener>... listeners); - - @Override - Promise removeListener(GenericFutureListener> listener); - - @Override - Promise removeListeners(GenericFutureListener>... listeners); - - @Override - Promise await() throws InterruptedException; - - @Override - Promise awaitUninterruptibly(); - - @Override - Promise sync() throws InterruptedException; - - @Override - Promise syncUninterruptibly(); -} diff --git a/java/src/game/net/util/concurrent/PromiseTask.java b/java/src/game/net/util/concurrent/PromiseTask.java deleted file mode 100644 index d195994..0000000 --- a/java/src/game/net/util/concurrent/PromiseTask.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.concurrent.Callable; -import java.util.concurrent.RunnableFuture; - -class PromiseTask extends DefaultPromise implements RunnableFuture { - - static Callable toCallable(Runnable runnable, T result) { - return new RunnableAdapter(runnable, result); - } - - private static final class RunnableAdapter implements Callable { - final Runnable task; - final T result; - - RunnableAdapter(Runnable task, T result) { - this.task = task; - this.result = result; - } - - @Override - public T call() { - task.run(); - return result; - } - - @Override - public String toString() { - return "Callable(task: " + task + ", result: " + result + ')'; - } - } - - protected final Callable task; - - PromiseTask(EventExecutor executor, Runnable runnable, V result) { - this(executor, toCallable(runnable, result)); - } - - PromiseTask(EventExecutor executor, Callable callable) { - super(executor); - task = callable; - } - - @Override - public final int hashCode() { - return System.identityHashCode(this); - } - - @Override - public final boolean equals(Object obj) { - return this == obj; - } - - @Override - public void run() { - try { - if (setUncancellableInternal()) { - V result = task.call(); - setSuccessInternal(result); - } - } catch (Throwable e) { - setFailureInternal(e); - } - } - - @Override - public final Promise setFailure(Throwable cause) { - throw new IllegalStateException(); - } - - protected final Promise setFailureInternal(Throwable cause) { - super.setFailure(cause); - return this; - } - - @Override - public final boolean tryFailure(Throwable cause) { - return false; - } - - protected final boolean tryFailureInternal(Throwable cause) { - return super.tryFailure(cause); - } - - @Override - public final Promise setSuccess(V result) { - throw new IllegalStateException(); - } - - protected final Promise setSuccessInternal(V result) { - super.setSuccess(result); - return this; - } - - @Override - public final boolean trySuccess(V result) { - return false; - } - - protected final boolean trySuccessInternal(V result) { - return super.trySuccess(result); - } - - @Override - public final boolean setUncancellable() { - throw new IllegalStateException(); - } - - protected final boolean setUncancellableInternal() { - return super.setUncancellable(); - } - - @Override - protected StringBuilder toStringBuilder() { - StringBuilder buf = super.toStringBuilder(); - buf.setCharAt(buf.length() - 1, ','); - buf.append(" task: "); - buf.append(task); - buf.append(')'); - return buf; - } -} diff --git a/java/src/game/net/util/concurrent/ScheduledFuture.java b/java/src/game/net/util/concurrent/ScheduledFuture.java deleted file mode 100644 index a699256..0000000 --- a/java/src/game/net/util/concurrent/ScheduledFuture.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -/** - * The result of an scheduled asynchronous operation. - */ - -public interface ScheduledFuture extends Future, java.util.concurrent.ScheduledFuture { -} diff --git a/java/src/game/net/util/concurrent/ScheduledFutureTask.java b/java/src/game/net/util/concurrent/ScheduledFutureTask.java deleted file mode 100644 index 93d3492..0000000 --- a/java/src/game/net/util/concurrent/ScheduledFutureTask.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.concurrent; - -import java.util.Queue; -import java.util.concurrent.Callable; -import java.util.concurrent.Delayed; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - - -final class ScheduledFutureTask extends PromiseTask implements ScheduledFuture { - private static final AtomicLong nextTaskId = new AtomicLong(); - private static final long START_TIME = System.nanoTime(); - - static long nanoTime() { - return System.nanoTime() - START_TIME; - } - - static long deadlineNanos(long delay) { - return nanoTime() + delay; - } - - private final long id = nextTaskId.getAndIncrement(); - private final Queue> delayedTaskQueue; - private long deadlineNanos; - /* 0 - no repeat, >0 - repeat at fixed rate, <0 - repeat with fixed delay */ - private final long periodNanos; - - ScheduledFutureTask( - EventExecutor executor, Queue> delayedTaskQueue, - Runnable runnable, V result, long nanoTime) { - - this(executor, delayedTaskQueue, toCallable(runnable, result), nanoTime); - } - - ScheduledFutureTask( - EventExecutor executor, Queue> delayedTaskQueue, - Callable callable, long nanoTime, long period) { - - super(executor, callable); - if (period == 0) { - throw new IllegalArgumentException("period: 0 (expected: != 0)"); - } - this.delayedTaskQueue = delayedTaskQueue; - deadlineNanos = nanoTime; - periodNanos = period; - } - - ScheduledFutureTask( - EventExecutor executor, Queue> delayedTaskQueue, - Callable callable, long nanoTime) { - - super(executor, callable); - this.delayedTaskQueue = delayedTaskQueue; - deadlineNanos = nanoTime; - periodNanos = 0; - } - - @Override - protected EventExecutor executor() { - return super.executor(); - } - - public long deadlineNanos() { - return deadlineNanos; - } - - public long delayNanos() { - return Math.max(0, deadlineNanos() - nanoTime()); - } - - public long delayNanos(long currentTimeNanos) { - return Math.max(0, deadlineNanos() - (currentTimeNanos - START_TIME)); - } - - @Override - public long getDelay(TimeUnit unit) { - return unit.convert(delayNanos(), TimeUnit.NANOSECONDS); - } - - @Override - public int compareTo(Delayed o) { - if (this == o) { - return 0; - } - - ScheduledFutureTask that = (ScheduledFutureTask) o; - long d = deadlineNanos() - that.deadlineNanos(); - if (d < 0) { - return -1; - } else if (d > 0) { - return 1; - } else if (id < that.id) { - return -1; - } else if (id == that.id) { - throw new Error(); - } else { - return 1; - } - } - - @Override - public void run() { - assert executor().inEventLoop(); - try { - if (periodNanos == 0) { - if (setUncancellableInternal()) { - V result = task.call(); - setSuccessInternal(result); - } - } else { - // check if is done as it may was cancelled - if (!isCancelled()) { - task.call(); - if (!executor().isShutdown()) { - long p = periodNanos; - if (p > 0) { - deadlineNanos += p; - } else { - deadlineNanos = nanoTime() - p; - } - if (!isCancelled()) { - delayedTaskQueue.add(this); - } - } - } - } - } catch (Throwable cause) { - setFailureInternal(cause); - } - } - - @Override - protected StringBuilder toStringBuilder() { - StringBuilder buf = super.toStringBuilder(); - buf.setCharAt(buf.length() - 1, ','); - buf.append(" id: "); - buf.append(id); - buf.append(", deadline: "); - buf.append(deadlineNanos); - buf.append(", period: "); - buf.append(periodNanos); - buf.append(')'); - return buf; - } -} diff --git a/java/src/game/net/util/concurrent/SingleThreadEventExecutor.java b/java/src/game/net/util/concurrent/SingleThreadEventExecutor.java deleted file mode 100644 index 1e0b117..0000000 --- a/java/src/game/net/util/concurrent/SingleThreadEventExecutor.java +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.PriorityQueue; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.Semaphore; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import game.net.util.internal.PlatformDependent; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * Abstract base class for {@link EventExecutor}'s that execute all its submitted tasks in a single thread. - * - */ -public abstract class SingleThreadEventExecutor extends AbstractEventExecutor { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(SingleThreadEventExecutor.class); - - private static final int ST_NOT_STARTED = 1; - private static final int ST_STARTED = 2; - private static final int ST_SHUTTING_DOWN = 3; - private static final int ST_SHUTDOWN = 4; - private static final int ST_TERMINATED = 5; - - private static final Runnable WAKEUP_TASK = new Runnable() { - @Override - public void run() { - // Do nothing. - } - }; - - private static final AtomicIntegerFieldUpdater STATE_UPDATER; - - static { - AtomicIntegerFieldUpdater updater = - PlatformDependent.newAtomicIntegerFieldUpdater(SingleThreadEventExecutor.class, "state"); - if (updater == null) { - updater = AtomicIntegerFieldUpdater.newUpdater(SingleThreadEventExecutor.class, "state"); - } - STATE_UPDATER = updater; - } - - private final EventExecutorGroup parent; - private final Queue taskQueue; - final Queue> delayedTaskQueue = new PriorityQueue>(); - - private final Thread thread; - private final Semaphore threadLock = new Semaphore(0); - private final Set shutdownHooks = new LinkedHashSet(); - private final boolean addTaskWakesUp; - - private long lastExecutionTime; - - - private volatile int state = ST_NOT_STARTED; - - private volatile long gracefulShutdownQuietPeriod; - private volatile long gracefulShutdownTimeout; - private long gracefulShutdownStartTime; - - private final Promise terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE); - - /** - * Create a new instance - * - * @param parent the {@link EventExecutorGroup} which is the parent of this instance and belongs to it - * @param threadFactory the {@link ThreadFactory} which will be used for the used {@link Thread} - * @param addTaskWakesUp {@code true} if and only if invocation of {@link #addTask(Runnable)} will wake up the - * executor thread - */ - protected SingleThreadEventExecutor( - EventExecutorGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) { - - if (threadFactory == null) { - throw new NullPointerException("threadFactory"); - } - - this.parent = parent; - this.addTaskWakesUp = addTaskWakesUp; - - thread = threadFactory.newThread(new Runnable() { - @Override - public void run() { - boolean success = false; - updateLastExecutionTime(); - try { - SingleThreadEventExecutor.this.run(); - success = true; - } catch (Throwable t) { - logger.warn("Unexpected exception from an event executor: ", t); - } finally { - for (;;) { - int oldState = STATE_UPDATER.get(SingleThreadEventExecutor.this); - if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet( - SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) { - break; - } - } - // Check if confirmShutdown() was called at the end of the loop. - if (success && gracefulShutdownStartTime == 0) { - logger.error( - "Buggy " + EventExecutor.class.getSimpleName() + " implementation; " + - SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must be called " + - "before run() implementation terminates."); - } - - try { - // Run all remaining tasks and shutdown hooks. - for (;;) { - if (confirmShutdown()) { - break; - } - } - } finally { - try { - cleanup(); - } finally { - STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED); - threadLock.release(); - if (!taskQueue.isEmpty()) { - logger.warn( - "An event executor terminated with " + - "non-empty task queue (" + taskQueue.size() + ')'); - } - - terminationFuture.setSuccess(null); - } - } - } - } - }); - - taskQueue = newTaskQueue(); - } - - /** - * Create a new {@link Queue} which will holds the tasks to execute. This default implementation will return a - * {@link LinkedBlockingQueue} but if your sub-class of {@link SingleThreadEventExecutor} will not do any blocking - * calls on the this {@link Queue} it may make sense to {@code @Override} this and return some more performant - * implementation that does not support blocking operations at all. - */ - protected Queue newTaskQueue() { - return new LinkedBlockingQueue(); - } - - @Override - public EventExecutorGroup parent() { - return parent; - } - - /** - * Interrupt the current running {@link Thread}. - */ - protected void interruptThread() { - thread.interrupt(); - } - - /** - * @see {@link Queue#poll()} - */ - protected Runnable pollTask() { - assert inEventLoop(); - for (;;) { - Runnable task = taskQueue.poll(); - if (task == WAKEUP_TASK) { - continue; - } - return task; - } - } - - /** - * Take the next {@link Runnable} from the task queue and so will block if no task is currently present. - *

- * Be aware that this method will throw an {@link UnsupportedOperationException} if the task queue, which was - * created via {@link #newTaskQueue()}, does not implement {@link BlockingQueue}. - *

- * - * @return {@code null} if the executor thread has been interrupted or waken up. - */ - protected Runnable takeTask() { - assert inEventLoop(); - if (!(taskQueue instanceof BlockingQueue)) { - throw new UnsupportedOperationException(); - } - - BlockingQueue taskQueue = (BlockingQueue) this.taskQueue; - for (;;) { - ScheduledFutureTask delayedTask = delayedTaskQueue.peek(); - if (delayedTask == null) { - Runnable task = null; - try { - task = taskQueue.take(); - if (task == WAKEUP_TASK) { - task = null; - } - } catch (InterruptedException e) { - // Ignore - } - return task; - } else { - long delayNanos = delayedTask.delayNanos(); - Runnable task = null; - if (delayNanos > 0) { - try { - task = taskQueue.poll(delayNanos, TimeUnit.NANOSECONDS); - } catch (InterruptedException e) { - return null; - } - } - if (task == null) { - // We need to fetch the delayed tasks now as otherwise there may be a chance that - // delayed tasks are never executed if there is always one task in the taskQueue. - // This is for example true for the read task of OIO Transport - // See https://github.com/netty/netty/issues/1614 - fetchFromDelayedQueue(); - task = taskQueue.poll(); - } - - if (task != null) { - return task; - } - } - } - } - - private void fetchFromDelayedQueue() { - long nanoTime = 0L; - for (;;) { - ScheduledFutureTask delayedTask = delayedTaskQueue.peek(); - if (delayedTask == null) { - break; - } - - if (nanoTime == 0L) { - nanoTime = ScheduledFutureTask.nanoTime(); - } - - if (delayedTask.deadlineNanos() <= nanoTime) { - delayedTaskQueue.remove(); - taskQueue.add(delayedTask); - } else { - break; - } - } - } - - /** - * @see {@link Queue#peek()} - */ - protected Runnable peekTask() { - assert inEventLoop(); - return taskQueue.peek(); - } - - /** - * @see {@link Queue#isEmpty()} - */ - protected boolean hasTasks() { - assert inEventLoop(); - return !taskQueue.isEmpty(); - } - - /** - * Returns {@code true} if a scheduled task is ready for processing by {@link #runAllTasks()} or - * {@link #runAllTasks(long)}. - */ - protected boolean hasScheduledTasks() { - assert inEventLoop(); - ScheduledFutureTask delayedTask = delayedTaskQueue.peek(); - return delayedTask != null && delayedTask.deadlineNanos() <= ScheduledFutureTask.nanoTime(); - } - - /** - * Return the number of tasks that are pending for processing. - * - * Be aware that this operation may be expensive as it depends on the internal implementation of the - * SingleThreadEventExecutor. So use it was care! - */ - public final int pendingTasks() { - return taskQueue.size(); - } - - /** - * Add a task to the task queue, or throws a {@link RejectedExecutionException} if this instance was shutdown - * before. - */ - protected void addTask(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - if (isShutdown()) { - reject(); - } - taskQueue.add(task); - } - - /** - * @see {@link Queue#remove(Object)} - */ - protected boolean removeTask(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - return taskQueue.remove(task); - } - - /** - * Poll all tasks from the task queue and run them via {@link Runnable#run()} method. - * - * @return {@code true} if and only if at least one task was run - */ - protected boolean runAllTasks() { - fetchFromDelayedQueue(); - Runnable task = pollTask(); - if (task == null) { - return false; - } - - for (;;) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("A task raised an exception.", t); - } - - task = pollTask(); - if (task == null) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - return true; - } - } - } - - /** - * Poll all tasks from the task queue and run them via {@link Runnable#run()} method. This method stops running - * the tasks in the task queue and returns if it ran longer than {@code timeoutNanos}. - */ - protected boolean runAllTasks(long timeoutNanos) { - fetchFromDelayedQueue(); - Runnable task = pollTask(); - if (task == null) { - return false; - } - - final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos; - long runTasks = 0; - long lastExecutionTime; - for (;;) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("A task raised an exception.", t); - } - - runTasks ++; - - // Check timeout every 64 tasks because nanoTime() is relatively expensive. - // XXX: Hard-coded value - will make it configurable if it is really a problem. - if ((runTasks & 0x3F) == 0) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - if (lastExecutionTime >= deadline) { - break; - } - } - - task = pollTask(); - if (task == null) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - break; - } - } - - this.lastExecutionTime = lastExecutionTime; - return true; - } - - /** - * Returns the amount of time left until the scheduled task with the closest dead line is executed. - */ - protected long delayNanos(long currentTimeNanos) { - ScheduledFutureTask delayedTask = delayedTaskQueue.peek(); - if (delayedTask == null) { - return SCHEDULE_PURGE_INTERVAL; - } - - return delayedTask.delayNanos(currentTimeNanos); - } - - /** - * Updates the internal timestamp that tells when a submitted task was executed most recently. - * {@link #runAllTasks()} and {@link #runAllTasks(long)} updates this timestamp automatically, and thus there's - * usually no need to call this method. However, if you take the tasks manually using {@link #takeTask()} or - * {@link #pollTask()}, you have to call this method at the end of task execution loop for accurate quiet period - * checks. - */ - protected void updateLastExecutionTime() { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - } - - /** - * - */ - protected abstract void run(); - - /** - * Do nothing, sub-classes may override - */ - protected void cleanup() { - // NOOP - } - - protected void wakeup(boolean inEventLoop) { - if (!inEventLoop || STATE_UPDATER.get(this) == ST_SHUTTING_DOWN) { - taskQueue.add(WAKEUP_TASK); - } - } - - @Override - public boolean inEventLoop(Thread thread) { - return thread == this.thread; - } - - /** - * Add a {@link Runnable} which will be executed on shutdown of this instance - */ - public void addShutdownHook(final Runnable task) { - if (inEventLoop()) { - shutdownHooks.add(task); - } else { - execute(new Runnable() { - @Override - public void run() { - shutdownHooks.add(task); - } - }); - } - } - - /** - * Remove a previous added {@link Runnable} as a shutdown hook - */ - public void removeShutdownHook(final Runnable task) { - if (inEventLoop()) { - shutdownHooks.remove(task); - } else { - execute(new Runnable() { - @Override - public void run() { - shutdownHooks.remove(task); - } - }); - } - } - - private boolean runShutdownHooks() { - boolean ran = false; - // Note shutdown hooks can add / remove shutdown hooks. - while (!shutdownHooks.isEmpty()) { - List copy = new ArrayList(shutdownHooks); - shutdownHooks.clear(); - for (Runnable task: copy) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("Shutdown hook raised an exception.", t); - } finally { - ran = true; - } - } - } - - if (ran) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - } - - return ran; - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - if (quietPeriod < 0) { - throw new IllegalArgumentException("quietPeriod: " + quietPeriod + " (expected >= 0)"); - } - if (timeout < quietPeriod) { - throw new IllegalArgumentException( - "timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (isShuttingDown()) { - return terminationFuture(); - } - - boolean inEventLoop = inEventLoop(); - boolean wakeup; - int oldState; - for (;;) { - if (isShuttingDown()) { - return terminationFuture(); - } - int newState; - wakeup = true; - oldState = STATE_UPDATER.get(this); - if (inEventLoop) { - newState = ST_SHUTTING_DOWN; - } else { - switch (oldState) { - case ST_NOT_STARTED: - case ST_STARTED: - newState = ST_SHUTTING_DOWN; - break; - default: - newState = oldState; - wakeup = false; - } - } - if (STATE_UPDATER.compareAndSet(this, oldState, newState)) { - break; - } - } - gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod); - gracefulShutdownTimeout = unit.toNanos(timeout); - - if (oldState == ST_NOT_STARTED) { - thread.start(); - } - - if (wakeup) { - wakeup(inEventLoop); - } - - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { - if (isShutdown()) { - return; - } - - boolean inEventLoop = inEventLoop(); - boolean wakeup; - int oldState; - for (;;) { - if (isShuttingDown()) { - return; - } - int newState; - wakeup = true; - oldState = STATE_UPDATER.get(this); - if (inEventLoop) { - newState = ST_SHUTDOWN; - } else { - switch (oldState) { - case ST_NOT_STARTED: - case ST_STARTED: - case ST_SHUTTING_DOWN: - newState = ST_SHUTDOWN; - break; - default: - newState = oldState; - wakeup = false; - } - } - if (STATE_UPDATER.compareAndSet(this, oldState, newState)) { - break; - } - } - - if (oldState == ST_NOT_STARTED) { - thread.start(); - } - - if (wakeup) { - wakeup(inEventLoop); - } - } - - @Override - public boolean isShuttingDown() { - return STATE_UPDATER.get(this) >= ST_SHUTTING_DOWN; - } - - @Override - public boolean isShutdown() { - return STATE_UPDATER.get(this) >= ST_SHUTDOWN; - } - - @Override - public boolean isTerminated() { - return STATE_UPDATER.get(this) == ST_TERMINATED; - } - - /** - * Confirm that the shutdown if the instance should be done now! - */ - protected boolean confirmShutdown() { - if (!isShuttingDown()) { - return false; - } - - if (!inEventLoop()) { - throw new IllegalStateException("must be invoked from an event loop"); - } - - cancelDelayedTasks(); - - if (gracefulShutdownStartTime == 0) { - gracefulShutdownStartTime = ScheduledFutureTask.nanoTime(); - } - - if (runAllTasks() || runShutdownHooks()) { - if (isShutdown()) { - // Executor shut down - no new tasks anymore. - return true; - } - - // There were tasks in the queue. Wait a little bit more until no tasks are queued for the quiet period. - wakeup(true); - return false; - } - - final long nanoTime = ScheduledFutureTask.nanoTime(); - - if (isShutdown() || nanoTime - gracefulShutdownStartTime > gracefulShutdownTimeout) { - return true; - } - - if (nanoTime - lastExecutionTime <= gracefulShutdownQuietPeriod) { - // Check if any tasks were added to the queue every 100ms. - // TODO: Change the behavior of takeTask() so that it returns on timeout. - wakeup(true); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // Ignore - } - - return false; - } - - // No tasks were added for last quiet period - hopefully safe to shut down. - // (Hopefully because we really cannot make a guarantee that there will be no execute() calls by a user.) - return true; - } - - private void cancelDelayedTasks() { - if (delayedTaskQueue.isEmpty()) { - return; - } - - final ScheduledFutureTask[] delayedTasks = - delayedTaskQueue.toArray(new ScheduledFutureTask[delayedTaskQueue.size()]); - - for (ScheduledFutureTask task: delayedTasks) { - task.cancel(false); - } - - delayedTaskQueue.clear(); - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (inEventLoop()) { - throw new IllegalStateException("cannot await termination of the current thread"); - } - - if (threadLock.tryAcquire(timeout, unit)) { - threadLock.release(); - } - - return isTerminated(); - } - - @Override - public void execute(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - - boolean inEventLoop = inEventLoop(); - if (inEventLoop) { - addTask(task); - } else { - startThread(); - addTask(task); - if (isShutdown() && removeTask(task)) { - reject(); - } - } - - if (!addTaskWakesUp && wakesUpForTask(task)) { - wakeup(inEventLoop); - } - } - - - protected boolean wakesUpForTask(Runnable task) { - return true; - } - - protected static void reject() { - throw new RejectedExecutionException("event executor terminated"); - } - - // ScheduledExecutorService implementation - - private static final long SCHEDULE_PURGE_INTERVAL = TimeUnit.SECONDS.toNanos(1); - - @Override - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { - if (command == null) { - throw new NullPointerException("command"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (delay < 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: >= 0)", delay)); - } - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, command, null, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay)))); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - if (callable == null) { - throw new NullPointerException("callable"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (delay < 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: >= 0)", delay)); - } - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, callable, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay)))); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - if (command == null) { - throw new NullPointerException("command"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (initialDelay < 0) { - throw new IllegalArgumentException( - String.format("initialDelay: %d (expected: >= 0)", initialDelay)); - } - if (period <= 0) { - throw new IllegalArgumentException( - String.format("period: %d (expected: > 0)", period)); - } - - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, Executors.callable(command, null), - ScheduledFutureTask.deadlineNanos(unit.toNanos(initialDelay)), unit.toNanos(period))); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - if (command == null) { - throw new NullPointerException("command"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (initialDelay < 0) { - throw new IllegalArgumentException( - String.format("initialDelay: %d (expected: >= 0)", initialDelay)); - } - if (delay <= 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: > 0)", delay)); - } - - return schedule(new ScheduledFutureTask( - this, delayedTaskQueue, Executors.callable(command, null), - ScheduledFutureTask.deadlineNanos(unit.toNanos(initialDelay)), -unit.toNanos(delay))); - } - - private ScheduledFuture schedule(final ScheduledFutureTask task) { - if (task == null) { - throw new NullPointerException("task"); - } - - if (inEventLoop()) { - delayedTaskQueue.add(task); - } else { - execute(new Runnable() { - @Override - public void run() { - delayedTaskQueue.add(task); - } - }); - } - - return task; - } - - private void startThread() { - if (STATE_UPDATER.get(this) == ST_NOT_STARTED) { - if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) { - delayedTaskQueue.add(new ScheduledFutureTask( - this, delayedTaskQueue, Executors.callable(new PurgeTask(), null), - ScheduledFutureTask.deadlineNanos(SCHEDULE_PURGE_INTERVAL), -SCHEDULE_PURGE_INTERVAL)); - thread.start(); - } - } - } - - private final class PurgeTask implements Runnable { - @Override - public void run() { - Iterator> i = delayedTaskQueue.iterator(); - while (i.hasNext()) { - ScheduledFutureTask task = i.next(); - if (task.isCancelled()) { - i.remove(); - } - } - } - } -} diff --git a/java/src/game/net/util/concurrent/SucceededFuture.java b/java/src/game/net/util/concurrent/SucceededFuture.java deleted file mode 100644 index 710ee3b..0000000 --- a/java/src/game/net/util/concurrent/SucceededFuture.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.concurrent; - -/** - * The {@link CompleteFuture} which is succeeded already. It is - * recommended to use {@link EventExecutor#newSucceededFuture(Object)} instead of - * calling the constructor of this future. - */ -public final class SucceededFuture extends CompleteFuture { - private final V result; - - /** - * Creates a new instance. - * - * @param executor the {@link EventExecutor} associated with this future - */ - public SucceededFuture(EventExecutor executor, V result) { - super(executor); - this.result = result; - } - - @Override - public Throwable cause() { - return null; - } - - @Override - public boolean isSuccess() { - return true; - } - - @Override - public V getNow() { - return result; - } -} diff --git a/java/src/game/net/util/internal/Cleaner0.java b/java/src/game/net/util/internal/Cleaner0.java deleted file mode 100644 index 66c6a75..0000000 --- a/java/src/game/net/util/internal/Cleaner0.java +++ /dev/null @@ -1,74 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ -package game.net.util.internal; - -import java.lang.reflect.Field; -import java.nio.ByteBuffer; - -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; -import sun.misc.Cleaner; - - -/** - * Allows to free direct {@link ByteBuffer} by using {@link Cleaner}. This is encapsulated in an extra class to be able - * to use {@link PlatformDependent0} on Android without problems. - * - * For more details see #2604. - */ -final class Cleaner0 { - private static final long CLEANER_FIELD_OFFSET; - private static final InternalLogger logger = InternalLoggerFactory.getInstance(Cleaner0.class); - - static { - ByteBuffer direct = ByteBuffer.allocateDirect(1); - Field cleanerField; - long fieldOffset = -1; - if (PlatformDependent0.hasUnsafe()) { - try { - cleanerField = direct.getClass().getDeclaredField("cleaner"); - cleanerField.setAccessible(true); - Cleaner cleaner = (Cleaner) cleanerField.get(direct); - cleaner.clean(); - fieldOffset = PlatformDependent0.objectFieldOffset(cleanerField); - } catch (Throwable t) { - // We don't have ByteBuffer.cleaner(). - fieldOffset = -1; - } - } - logger.debug("java.nio.ByteBuffer.cleaner(): {}", fieldOffset != -1? "available" : "unavailable"); - CLEANER_FIELD_OFFSET = fieldOffset; - - // free buffer if possible - freeDirectBuffer(direct); - } - - static void freeDirectBuffer(ByteBuffer buffer) { - if (CLEANER_FIELD_OFFSET == -1 || !buffer.isDirect()) { - return; - } - try { - Cleaner cleaner = (Cleaner) PlatformDependent0.getObject(buffer, CLEANER_FIELD_OFFSET); - if (cleaner != null) { - cleaner.clean(); - } - } catch (Throwable t) { - // Nothing we can do here. - } - } - - private Cleaner0() { } -} diff --git a/java/src/game/net/util/internal/EmptyArrays.java b/java/src/game/net/util/internal/EmptyArrays.java deleted file mode 100644 index c468a63..0000000 --- a/java/src/game/net/util/internal/EmptyArrays.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.nio.ByteBuffer; -import java.security.cert.X509Certificate; - -public final class EmptyArrays { - - public static final byte[] EMPTY_BYTES = new byte[0]; - public static final boolean[] EMPTY_BOOLEANS = new boolean[0]; - public static final double[] EMPTY_DOUBLES = new double[0]; - public static final float[] EMPTY_FLOATS = new float[0]; - public static final int[] EMPTY_INTS = new int[0]; - public static final short[] EMPTY_SHORTS = new short[0]; - public static final long[] EMPTY_LONGS = new long[0]; - public static final Object[] EMPTY_OBJECTS = new Object[0]; - public static final Class[] EMPTY_CLASSES = new Class[0]; - public static final String[] EMPTY_STRINGS = new String[0]; - public static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; - public static final ByteBuffer[] EMPTY_BYTE_BUFFERS = new ByteBuffer[0]; - public static final X509Certificate[] EMPTY_X509_CERTIFICATES = new X509Certificate[0]; - - private EmptyArrays() { } -} diff --git a/java/src/game/net/util/internal/IntegerHolder.java b/java/src/game/net/util/internal/IntegerHolder.java deleted file mode 100644 index 4634068..0000000 --- a/java/src/game/net/util/internal/IntegerHolder.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -public final class IntegerHolder { - public int value; -} diff --git a/java/src/game/net/util/internal/InternalThreadLocalMap.java b/java/src/game/net/util/internal/InternalThreadLocalMap.java deleted file mode 100644 index f42ba2a..0000000 --- a/java/src/game/net/util/internal/InternalThreadLocalMap.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.util.Arrays; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.WeakHashMap; - -import game.net.util.concurrent.FastThreadLocalThread; - -/** - * The internal data structure that stores the thread-local variables for Netty and all {@link FastThreadLocal}s. - * Note that this class is for internal use only and is subject to change at any time. Use {@link FastThreadLocal} - * unless you know what you are doing. - */ -public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap { - - public static final Object UNSET = new Object(); - - public static InternalThreadLocalMap getIfSet() { - Thread thread = Thread.currentThread(); - InternalThreadLocalMap threadLocalMap; - if (thread instanceof FastThreadLocalThread) { - threadLocalMap = ((FastThreadLocalThread) thread).threadLocalMap(); - } else { - ThreadLocal slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap; - if (slowThreadLocalMap == null) { - threadLocalMap = null; - } else { - threadLocalMap = slowThreadLocalMap.get(); - } - } - return threadLocalMap; - } - - public static InternalThreadLocalMap get() { - Thread thread = Thread.currentThread(); - if (thread instanceof FastThreadLocalThread) { - return fastGet((FastThreadLocalThread) thread); - } else { - return slowGet(); - } - } - - private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) { - InternalThreadLocalMap threadLocalMap = thread.threadLocalMap(); - if (threadLocalMap == null) { - thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap()); - } - return threadLocalMap; - } - - private static InternalThreadLocalMap slowGet() { - ThreadLocal slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap; - if (slowThreadLocalMap == null) { - UnpaddedInternalThreadLocalMap.slowThreadLocalMap = - slowThreadLocalMap = new ThreadLocal(); - } - - InternalThreadLocalMap ret = slowThreadLocalMap.get(); - if (ret == null) { - ret = new InternalThreadLocalMap(); - slowThreadLocalMap.set(ret); - } - return ret; - } - - public static void remove() { - Thread thread = Thread.currentThread(); - if (thread instanceof FastThreadLocalThread) { - ((FastThreadLocalThread) thread).setThreadLocalMap(null); - } else { - ThreadLocal slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap; - if (slowThreadLocalMap != null) { - slowThreadLocalMap.remove(); - } - } - } - - public static void destroy() { - slowThreadLocalMap = null; - } - - public static int nextVariableIndex() { - int index = nextIndex.getAndIncrement(); - if (index < 0) { - nextIndex.decrementAndGet(); - throw new IllegalStateException("too many thread-local indexed variables"); - } - return index; - } - - public static int lastVariableIndex() { - return nextIndex.get() - 1; - } - - // Cache line padding (must be public) - // With CompressedOops enabled, an instance of this class should occupy at least 128 bytes. - public long rp1, rp2, rp3, rp4, rp5, rp6, rp7, rp8, rp9; - - private InternalThreadLocalMap() { - super(newIndexedVariableTable()); - } - - private static Object[] newIndexedVariableTable() { - Object[] array = new Object[32]; - Arrays.fill(array, UNSET); - return array; - } - - public int size() { - int count = 0; - - if (futureListenerStackDepth != 0) { - count ++; - } - if (localChannelReaderStackDepth != 0) { - count ++; - } - if (handlerSharableCache != null) { - count ++; - } - if (counterHashCode != null) { - count ++; - } - if (random != null) { - count ++; - } - if (typeParameterMatcherGetCache != null) { - count ++; - } - if (typeParameterMatcherFindCache != null) { - count ++; - } - if (stringBuilder != null) { - count ++; - } - if (charsetEncoderCache != null) { - count ++; - } - if (charsetDecoderCache != null) { - count ++; - } - - for (Object o: indexedVariables) { - if (o != UNSET) { - count ++; - } - } - - // We should subtract 1 from the count because the first element in 'indexedVariables' is reserved - // by 'FastThreadLocal' to keep the list of 'FastThreadLocal's to remove on 'FastThreadLocal.removeAll()'. - return count - 1; - } - - public StringBuilder stringBuilder() { - StringBuilder builder = stringBuilder; - if (builder == null) { - stringBuilder = builder = new StringBuilder(512); - } else { - builder.setLength(0); - } - return builder; - } - - public Map charsetEncoderCache() { - Map cache = charsetEncoderCache; - if (cache == null) { - charsetEncoderCache = cache = new IdentityHashMap(); - } - return cache; - } - - public Map charsetDecoderCache() { - Map cache = charsetDecoderCache; - if (cache == null) { - charsetDecoderCache = cache = new IdentityHashMap(); - } - return cache; - } - - public int futureListenerStackDepth() { - return futureListenerStackDepth; - } - - public void setFutureListenerStackDepth(int futureListenerStackDepth) { - this.futureListenerStackDepth = futureListenerStackDepth; - } - - public ThreadLocalRandom random() { - ThreadLocalRandom r = random; - if (r == null) { - random = r = new ThreadLocalRandom(); - } - return r; - } - - public Map, TypeParameterMatcher> typeParameterMatcherGetCache() { - Map, TypeParameterMatcher> cache = typeParameterMatcherGetCache; - if (cache == null) { - typeParameterMatcherGetCache = cache = new IdentityHashMap, TypeParameterMatcher>(); - } - return cache; - } - - public Map, Map> typeParameterMatcherFindCache() { - Map, Map> cache = typeParameterMatcherFindCache; - if (cache == null) { - typeParameterMatcherFindCache = cache = new IdentityHashMap, Map>(); - } - return cache; - } - - public IntegerHolder counterHashCode() { - return counterHashCode; - } - - public void setCounterHashCode(IntegerHolder counterHashCode) { - this.counterHashCode = counterHashCode; - } - - public Map, Boolean> handlerSharableCache() { - Map, Boolean> cache = handlerSharableCache; - if (cache == null) { - // Start with small capacity to keep memory overhead as low as possible. - handlerSharableCache = cache = new WeakHashMap, Boolean>(4); - } - return cache; - } - - public int localChannelReaderStackDepth() { - return localChannelReaderStackDepth; - } - - public void setLocalChannelReaderStackDepth(int localChannelReaderStackDepth) { - this.localChannelReaderStackDepth = localChannelReaderStackDepth; - } - - public Object indexedVariable(int index) { - Object[] lookup = indexedVariables; - return index < lookup.length? lookup[index] : UNSET; - } - - /** - * @return {@code true} if and only if a new thread-local variable has been created - */ - public boolean setIndexedVariable(int index, Object value) { - Object[] lookup = indexedVariables; - if (index < lookup.length) { - Object oldValue = lookup[index]; - lookup[index] = value; - return oldValue == UNSET; - } else { - expandIndexedVariableTableAndSet(index, value); - return true; - } - } - - private void expandIndexedVariableTableAndSet(int index, Object value) { - Object[] oldArray = indexedVariables; - final int oldCapacity = oldArray.length; - int newCapacity = index; - newCapacity |= newCapacity >>> 1; - newCapacity |= newCapacity >>> 2; - newCapacity |= newCapacity >>> 4; - newCapacity |= newCapacity >>> 8; - newCapacity |= newCapacity >>> 16; - newCapacity ++; - - Object[] newArray = Arrays.copyOf(oldArray, newCapacity); - Arrays.fill(newArray, oldCapacity, newArray.length, UNSET); - newArray[index] = value; - indexedVariables = newArray; - } - - public Object removeIndexedVariable(int index) { - Object[] lookup = indexedVariables; - if (index < lookup.length) { - Object v = lookup[index]; - lookup[index] = UNSET; - return v; - } else { - return UNSET; - } - } - - public boolean isIndexedVariableSet(int index) { - Object[] lookup = indexedVariables; - return index < lookup.length && lookup[index] != UNSET; - } -} diff --git a/java/src/game/net/util/internal/MpscLinkedQueue.java b/java/src/game/net/util/internal/MpscLinkedQueue.java deleted file mode 100644 index 5dfacc1..0000000 --- a/java/src/game/net/util/internal/MpscLinkedQueue.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (C) 2009-2013 Typesafe Inc. - */ -package game.net.util.internal; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Queue; - -/** - * A lock-free concurrent single-consumer multi-producer {@link Queue}. - * It allows multiple producer threads to perform the following operations simultaneously: - *
    - *
  • {@link #offer(Object)}, {@link #add(Object)}, and {@link #addAll(Collection)}
  • - *
  • All other read-only operations: - *
      - *
    • {@link #contains(Object)} and {@link #containsAll(Collection)}
    • - *
    • {@link #element()}, {@link #peek()}
    • - *
    • {@link #size()} and {@link #isEmpty()}
    • - *
    • {@link #iterator()} (except {@link Iterator#remove()}
    • - *
    • {@link #toArray()} and {@link #toArray(Object[])}
    • - *
    - *
  • - *
- * .. while only one consumer thread is allowed to perform the following operations exclusively: - *
    - *
  • {@link #poll()} and {@link #remove()}
  • - *
  • {@link #remove(Object)}, {@link #removeAll(Collection)}, and {@link #retainAll(Collection)}
  • - *
  • {@link #clear()}
  • {@link #} - *
- * - * The behavior of this implementation is undefined if you perform the operations for a consumer thread only - * from multiple threads. - * - * The initial implementation is based on: - * - * and adopted padded head node changes from: - * - * data structure modified to avoid false sharing between head and tail Ref as per implementation of MpscLinkedQueue - * on JCTools project. - */ -final class MpscLinkedQueue extends MpscLinkedQueueTailRef implements Queue { - - private static final long serialVersionUID = -1878402552271506449L; - - long p00, p01, p02, p03, p04, p05, p06, p07; - long p30, p31, p32, p33, p34, p35, p36, p37; - - // offer() occurs at the tail of the linked list. - // poll() occurs at the head of the linked list. - // - // Resulting layout is: - // - // head --next--> 1st element --next--> 2nd element --next--> ... tail (last element) - // - // where the head is a dummy node whose value is null. - // - // offer() appends a new node next to the tail using AtomicReference.getAndSet() - // poll() removes head from the linked list and promotes the 1st element to the head, - // setting its value to null if possible. - // - // Also note that this class extends AtomicReference for the "tail" slot (which is the one that is appended to) - // since Unsafe does not expose XCHG operation intrinsically. - MpscLinkedQueue() { - MpscLinkedQueueNode tombstone = new DefaultNode(null); - setHeadRef(tombstone); - setTailRef(tombstone); - } - - /** - * Returns the node right next to the head, which contains the first element of this queue. - */ - private MpscLinkedQueueNode peekNode() { - for (;;) { - final MpscLinkedQueueNode head = headRef(); - final MpscLinkedQueueNode next = head.next(); - if (next != null) { - return next; - } - if (head == tailRef()) { - return null; - } - - // If we are here, it means: - // * offer() is adding the first element, and - // * it's between replaceTail(newTail) and oldTail.setNext(newTail). - // (i.e. next == oldTail and oldTail.next == null and head == oldTail != newTail) - } - } - - @Override - - public boolean offer(E value) { - if (value == null) { - throw new NullPointerException("value"); - } - - final MpscLinkedQueueNode newTail; - if (value instanceof MpscLinkedQueueNode) { - newTail = (MpscLinkedQueueNode) value; - newTail.setNext(null); - } else { - newTail = new DefaultNode(value); - } - - MpscLinkedQueueNode oldTail = getAndSetTailRef(newTail); - oldTail.setNext(newTail); - return true; - } - - @Override - public E poll() { - final MpscLinkedQueueNode next = peekNode(); - if (next == null) { - return null; - } - - // next becomes a new head. - MpscLinkedQueueNode oldHead = headRef(); - // Similar to 'headRef.node = next', but slightly faster (storestore vs loadstore) - // See: http://robsjava.blogspot.com/2013/06/a-faster-volatile.html - // See: http://psy-lob-saw.blogspot.com/2012/12/atomiclazyset-is-performance-win-for.html - lazySetHeadRef(next); - - // Break the linkage between the old head and the new head. - oldHead.unlink(); - - return next.clearMaybe(); - } - - @Override - public E peek() { - final MpscLinkedQueueNode next = peekNode(); - if (next == null) { - return null; - } - return next.value(); - } - - @Override - public int size() { - int count = 0; - MpscLinkedQueueNode n = peekNode(); - for (;;) { - if (n == null) { - break; - } - count ++; - n = n.next(); - } - return count; - } - - @Override - public boolean isEmpty() { - return peekNode() == null; - } - - @Override - public boolean contains(Object o) { - MpscLinkedQueueNode n = peekNode(); - for (;;) { - if (n == null) { - break; - } - if (n.value() == o) { - return true; - } - n = n.next(); - } - return false; - } - - @Override - public Iterator iterator() { - return new Iterator() { - private MpscLinkedQueueNode node = peekNode(); - - @Override - public boolean hasNext() { - return node != null; - } - - @Override - public E next() { - MpscLinkedQueueNode node = this.node; - if (node == null) { - throw new NoSuchElementException(); - } - E value = node.value(); - this.node = node.next(); - return value; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public boolean add(E e) { - if (offer(e)) { - return true; - } - throw new IllegalStateException("queue full"); - } - - @Override - public E remove() { - E e = poll(); - if (e != null) { - return e; - } - throw new NoSuchElementException(); - } - - @Override - public E element() { - E e = peek(); - if (e != null) { - return e; - } - throw new NoSuchElementException(); - } - - @Override - public Object[] toArray() { - final Object[] array = new Object[size()]; - final Iterator it = iterator(); - for (int i = 0; i < array.length; i ++) { - if (it.hasNext()) { - array[i] = it.next(); - } else { - return Arrays.copyOf(array, i); - } - } - return array; - } - - @Override - - public T[] toArray(T[] a) { - final int size = size(); - final T[] array; - if (a.length >= size) { - array = a; - } else { - array = (T[]) Array.newInstance(a.getClass().getComponentType(), size); - } - - final Iterator it = iterator(); - for (int i = 0; i < array.length; i++) { - if (it.hasNext()) { - array[i] = (T) it.next(); - } else { - if (a == array) { - array[i] = null; - return array; - } - - if (a.length < i) { - return Arrays.copyOf(array, i); - } - - System.arraycopy(array, 0, a, 0, i); - if (a.length > i) { - a[i] = null; - } - return a; - } - } - return array; - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsAll(Collection c) { - for (Object e: c) { - if (!contains(e)) { - return false; - } - } - return true; - } - - @Override - public boolean addAll(Collection c) { - if (c == null) { - throw new NullPointerException("c"); - } - if (c == this) { - throw new IllegalArgumentException("c == this"); - } - - boolean modified = false; - for (E e: c) { - add(e); - modified = true; - } - return modified; - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - while (poll() != null) { - continue; - } - } - - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - for (E e: this) { - out.writeObject(e); - } - out.writeObject(null); - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - - final MpscLinkedQueueNode tombstone = new DefaultNode(null); - setHeadRef(tombstone); - setTailRef(tombstone); - - for (;;) { - - E e = (E) in.readObject(); - if (e == null) { - break; - } - add(e); - } - } - - private static final class DefaultNode extends MpscLinkedQueueNode { - - private T value; - - DefaultNode(T value) { - this.value = value; - } - - @Override - public T value() { - return value; - } - - @Override - protected T clearMaybe() { - T value = this.value; - this.value = null; - return value; - } - } -} diff --git a/java/src/game/net/util/internal/MpscLinkedQueueHeadRef.java b/java/src/game/net/util/internal/MpscLinkedQueueHeadRef.java deleted file mode 100644 index d87efd6..0000000 --- a/java/src/game/net/util/internal/MpscLinkedQueueHeadRef.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.io.Serializable; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - - -abstract class MpscLinkedQueueHeadRef extends MpscLinkedQueuePad0 implements Serializable { - - private static final long serialVersionUID = 8467054865577874285L; - - - private static final AtomicReferenceFieldUpdater UPDATER; - - static { - - AtomicReferenceFieldUpdater updater; - updater = PlatformDependent.newAtomicReferenceFieldUpdater(MpscLinkedQueueHeadRef.class, "headRef"); - if (updater == null) { - updater = AtomicReferenceFieldUpdater.newUpdater( - MpscLinkedQueueHeadRef.class, MpscLinkedQueueNode.class, "headRef"); - } - UPDATER = updater; - } - - private transient volatile MpscLinkedQueueNode headRef; - - protected final MpscLinkedQueueNode headRef() { - return headRef; - } - - protected final void setHeadRef(MpscLinkedQueueNode headRef) { - this.headRef = headRef; - } - - protected final void lazySetHeadRef(MpscLinkedQueueNode headRef) { - UPDATER.lazySet(this, headRef); - } -} diff --git a/java/src/game/net/util/internal/MpscLinkedQueueNode.java b/java/src/game/net/util/internal/MpscLinkedQueueNode.java deleted file mode 100644 index ece1cd4..0000000 --- a/java/src/game/net/util/internal/MpscLinkedQueueNode.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -public abstract class MpscLinkedQueueNode { - - - private static final AtomicReferenceFieldUpdater nextUpdater; - - static { - - AtomicReferenceFieldUpdater u; - - u = PlatformDependent.newAtomicReferenceFieldUpdater(MpscLinkedQueueNode.class, "next"); - if (u == null) { - u = AtomicReferenceFieldUpdater.newUpdater(MpscLinkedQueueNode.class, MpscLinkedQueueNode.class, "next"); - } - nextUpdater = u; - } - - - private volatile MpscLinkedQueueNode next; - - final MpscLinkedQueueNode next() { - return next; - } - - final void setNext(final MpscLinkedQueueNode newNext) { - // Similar to 'next = newNext', but slightly faster (storestore vs loadstore) - // See: http://robsjava.blogspot.com/2013/06/a-faster-volatile.html - nextUpdater.lazySet(this, newNext); - } - - public abstract T value(); - - /** - * Sets the element this node contains to {@code null} so that the node can be used as a tombstone. - */ - protected T clearMaybe() { - return value(); - } - - /** - * Unlink to allow GC'ed - */ - void unlink() { - setNext(null); - } -} diff --git a/java/src/game/net/util/internal/MpscLinkedQueuePad0.java b/java/src/game/net/util/internal/MpscLinkedQueuePad0.java deleted file mode 100644 index b3db5c3..0000000 --- a/java/src/game/net/util/internal/MpscLinkedQueuePad0.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -abstract class MpscLinkedQueuePad0 { - long p00, p01, p02, p03, p04, p05, p06, p07; - long p30, p31, p32, p33, p34, p35, p36, p37; -} diff --git a/java/src/game/net/util/internal/MpscLinkedQueuePad1.java b/java/src/game/net/util/internal/MpscLinkedQueuePad1.java deleted file mode 100644 index e7fe206..0000000 --- a/java/src/game/net/util/internal/MpscLinkedQueuePad1.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -abstract class MpscLinkedQueuePad1 extends MpscLinkedQueueHeadRef { - - private static final long serialVersionUID = 2886694927079691637L; - - long p00, p01, p02, p03, p04, p05, p06, p07; - long p30, p31, p32, p33, p34, p35, p36, p37; -} diff --git a/java/src/game/net/util/internal/MpscLinkedQueueTailRef.java b/java/src/game/net/util/internal/MpscLinkedQueueTailRef.java deleted file mode 100644 index be2406b..0000000 --- a/java/src/game/net/util/internal/MpscLinkedQueueTailRef.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -abstract class MpscLinkedQueueTailRef extends MpscLinkedQueuePad1 { - - private static final long serialVersionUID = 8717072462993327429L; - - - private static final AtomicReferenceFieldUpdater UPDATER; - - static { - - AtomicReferenceFieldUpdater updater; - updater = PlatformDependent.newAtomicReferenceFieldUpdater(MpscLinkedQueueTailRef.class, "tailRef"); - if (updater == null) { - updater = AtomicReferenceFieldUpdater.newUpdater( - MpscLinkedQueueTailRef.class, MpscLinkedQueueNode.class, "tailRef"); - } - UPDATER = updater; - } - - private transient volatile MpscLinkedQueueNode tailRef; - - protected final MpscLinkedQueueNode tailRef() { - return tailRef; - } - - protected final void setTailRef(MpscLinkedQueueNode tailRef) { - this.tailRef = tailRef; - } - - - protected final MpscLinkedQueueNode getAndSetTailRef(MpscLinkedQueueNode tailRef) { - // LOCK XCHG in JDK8, a CAS loop in JDK 7/6 - return (MpscLinkedQueueNode) UPDATER.getAndSet(this, tailRef); - } -} diff --git a/java/src/game/net/util/internal/NoOpTypeParameterMatcher.java b/java/src/game/net/util/internal/NoOpTypeParameterMatcher.java deleted file mode 100644 index 6fe60b3..0000000 --- a/java/src/game/net/util/internal/NoOpTypeParameterMatcher.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -public final class NoOpTypeParameterMatcher extends TypeParameterMatcher { - @Override - public boolean match(Object msg) { - return true; - } -} diff --git a/java/src/game/net/util/internal/OneTimeTask.java b/java/src/game/net/util/internal/OneTimeTask.java deleted file mode 100644 index de25384..0000000 --- a/java/src/game/net/util/internal/OneTimeTask.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -/** - * {@link Runnable} which represent a one time task which may allow the {@link EventExecutor} to reduce the amount of - * produced garbage when queue it for execution. - * - * It is important this will not be reused. After submitted it is not allowed to get submitted again! - */ -public abstract class OneTimeTask extends MpscLinkedQueueNode implements Runnable { - - @Override - public Runnable value() { - return this; - } -} diff --git a/java/src/game/net/util/internal/PlatformDependent.java b/java/src/game/net/util/internal/PlatformDependent.java deleted file mode 100644 index b43d83d..0000000 --- a/java/src/game/net/util/internal/PlatformDependent.java +++ /dev/null @@ -1,844 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import game.net.util.CharsetUtil; -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - - -/** - * Utility that detects various properties specific to the current runtime - * environment, such as Java version and the availability of the - * {@code sun.misc.Unsafe} object. - *

- * You can disable the use of {@code sun.misc.Unsafe} if you specify - * the system property io.netty.noUnsafe. - */ -public final class PlatformDependent { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent.class); - - private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile( - "\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$"); - - private static final boolean IS_ANDROID = isAndroid0(); - private static final boolean IS_WINDOWS = isWindows0(); - private static final boolean IS_ROOT = isRoot0(); - - private static final int JAVA_VERSION = javaVersion0(); - - private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid(); - - private static final boolean HAS_UNSAFE = hasUnsafe0(); -// private static final boolean CAN_USE_CHM_V8 = HAS_UNSAFE && JAVA_VERSION < 8; - private static final boolean DIRECT_BUFFER_PREFERRED = - HAS_UNSAFE && !SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false); - private static final long MAX_DIRECT_MEMORY = maxDirectMemory0(); - - private static final long ARRAY_BASE_OFFSET = arrayBaseOffset0(); - -// private static final boolean HAS_JAVASSIST = hasJavassist0(); - -// private static final File TMPDIR = tmpdir0(); -// -// private static final int BIT_MODE = bitMode0(); -// -// private static final int ADDRESS_SIZE = addressSize0(); - - static { - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.noPreferDirect: {}", !DIRECT_BUFFER_PREFERRED); - } - - if (!hasUnsafe() && !isAndroid()) { - logger.info( - "Your platform does not provide complete low-level API for accessing direct buffers reliably. " + - "Unless explicitly requested, heap buffer will always be preferred to avoid potential system " + - "unstability."); - } - } - - /** - * Returns {@code true} if and only if the current platform is Android - */ - public static boolean isAndroid() { - return IS_ANDROID; - } - - /** - * Return {@code true} if the JVM is running on Windows - */ - public static boolean isWindows() { - return IS_WINDOWS; - } - - /** - * Return {@code true} if the current user is root. Note that this method returns - * {@code false} if on Windows. - */ - public static boolean isRoot() { - return IS_ROOT; - } - - /** - * Return the version of Java under which this library is used. - */ - public static int javaVersion() { - return JAVA_VERSION; - } - - /** - * Returns {@code true} if and only if it is fine to enable TCP_NODELAY socket option by default. - */ - public static boolean canEnableTcpNoDelayByDefault() { - return CAN_ENABLE_TCP_NODELAY_BY_DEFAULT; - } - - /** - * Return {@code true} if {@code sun.misc.Unsafe} was found on the classpath and can be used for acclerated - * direct memory access. - */ - public static boolean hasUnsafe() { - return HAS_UNSAFE; - } - - /** - * Returns {@code true} if the platform has reliable low-level direct buffer access API and a user specified - * {@code -Dio.netty.preferDirect} option. - */ - public static boolean directBufferPreferred() { - return DIRECT_BUFFER_PREFERRED; - } - - /** - * Returns the maximum memory reserved for direct buffer allocation. - */ - public static long maxDirectMemory() { - return MAX_DIRECT_MEMORY; - } - - /** - * Returns {@code true} if and only if Javassist is available. - */ -// public static boolean hasJavassist() { -// return HAS_JAVASSIST; -// } - - /** - * Returns the temporary directory. - */ -// public static File tmpdir() { -// return TMPDIR; -// } - - /** - * Returns the bit mode of the current VM (usually 32 or 64.) - */ -// public static int bitMode() { -// return BIT_MODE; -// } - - /** - * Return the address size of the OS. - * 4 (for 32 bits systems ) and 8 (for 64 bits systems). - */ -// public static int addressSize() { -// return ADDRESS_SIZE; -// } - -// public static long allocateMemory(long size) { -// return PlatformDependent0.allocateMemory(size); -// } - -// public static void freeMemory(long address) { -// PlatformDependent0.freeMemory(address); -// } - - /** - * Raises an exception bypassing compiler checks for checked exceptions. - */ - public static void throwException(Throwable t) { - if (hasUnsafe()) { - PlatformDependent0.throwException(t); - } else { - PlatformDependent.throwException0(t); - } - } - - - private static void throwException0(Throwable t) throws E { - throw (E) t; - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap() { -// if (CAN_USE_CHM_V8) { -// return new ConcurrentHashMapV8(); -// } else { - return new ConcurrentHashMap(); -// } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap(int initialCapacity) { -// if (CAN_USE_CHM_V8) { -// return new ConcurrentHashMapV8(initialCapacity); -// } else { - return new ConcurrentHashMap(initialCapacity); -// } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap(int initialCapacity, float loadFactor) { -// if (CAN_USE_CHM_V8) { -// return new ConcurrentHashMapV8(initialCapacity, loadFactor); -// } else { - return new ConcurrentHashMap(initialCapacity, loadFactor); -// } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap( - int initialCapacity, float loadFactor, int concurrencyLevel) { -// if (CAN_USE_CHM_V8) { -// return new ConcurrentHashMapV8(initialCapacity, loadFactor, concurrencyLevel); -// } else { - return new ConcurrentHashMap(initialCapacity, loadFactor, concurrencyLevel); -// } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap(Map map) { -// if (CAN_USE_CHM_V8) { -// return new ConcurrentHashMapV8(map); -// } else { - return new ConcurrentHashMap(map); -// } - } - - /** - * Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if - * the current platform does not support this operation or the specified buffer is not a direct buffer. - */ - public static void freeDirectBuffer(ByteBuffer buffer) { - if (hasUnsafe() && !isAndroid()) { - // only direct to method if we are not running on android. - // See https://github.com/netty/netty/issues/2604 - PlatformDependent0.freeDirectBuffer(buffer); - } - } - - public static long directBufferAddress(ByteBuffer buffer) { - return PlatformDependent0.directBufferAddress(buffer); - } - - public static Object getObject(Object object, long fieldOffset) { - return PlatformDependent0.getObject(object, fieldOffset); - } - - public static Object getObjectVolatile(Object object, long fieldOffset) { - return PlatformDependent0.getObjectVolatile(object, fieldOffset); - } - - public static int getInt(Object object, long fieldOffset) { - return PlatformDependent0.getInt(object, fieldOffset); - } - - public static long objectFieldOffset(Field field) { - return PlatformDependent0.objectFieldOffset(field); - } - - public static byte getByte(long address) { - return PlatformDependent0.getByte(address); - } - - public static short getShort(long address) { - return PlatformDependent0.getShort(address); - } - - public static int getInt(long address) { - return PlatformDependent0.getInt(address); - } - - public static long getLong(long address) { - return PlatformDependent0.getLong(address); - } - - public static void putOrderedObject(Object object, long address, Object value) { - PlatformDependent0.putOrderedObject(object, address, value); - } - - public static void putByte(long address, byte value) { - PlatformDependent0.putByte(address, value); - } - - public static void putShort(long address, short value) { - PlatformDependent0.putShort(address, value); - } - - public static void putInt(long address, int value) { - PlatformDependent0.putInt(address, value); - } - - public static void putLong(long address, long value) { - PlatformDependent0.putLong(address, value); - } - - public static void copyMemory(long srcAddr, long dstAddr, long length) { - PlatformDependent0.copyMemory(srcAddr, dstAddr, length); - } - - public static void copyMemory(byte[] src, int srcIndex, long dstAddr, long length) { - PlatformDependent0.copyMemory(src, ARRAY_BASE_OFFSET + srcIndex, null, dstAddr, length); - } - - public static void copyMemory(long srcAddr, byte[] dst, int dstIndex, long length) { - PlatformDependent0.copyMemory(null, srcAddr, dst, ARRAY_BASE_OFFSET + dstIndex, length); - } - - /** - * Create a new optimized {@link AtomicReferenceFieldUpdater} or {@code null} if it - * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned - * use {@link AtomicReferenceFieldUpdater#newUpdater(Class, Class, String)} as fallback. - */ - public static AtomicReferenceFieldUpdater newAtomicReferenceFieldUpdater( - Class tclass, String fieldName) { - if (hasUnsafe()) { - try { - return PlatformDependent0.newAtomicReferenceFieldUpdater(tclass, fieldName); - } catch (Throwable ignore) { - // ignore - } - } - return null; - } - - /** - * Create a new optimized {@link AtomicIntegerFieldUpdater} or {@code null} if it - * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned - * use {@link AtomicIntegerFieldUpdater#newUpdater(Class, String)} as fallback. - */ - public static AtomicIntegerFieldUpdater newAtomicIntegerFieldUpdater( - Class tclass, String fieldName) { - if (hasUnsafe()) { - try { - return PlatformDependent0.newAtomicIntegerFieldUpdater(tclass, fieldName); - } catch (Throwable ignore) { - // ignore - } - } - return null; - } - - /** - * Create a new optimized {@link AtomicLongFieldUpdater} or {@code null} if it - * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned - * use {@link AtomicLongFieldUpdater#newUpdater(Class, String)} as fallback. - */ - public static AtomicLongFieldUpdater newAtomicLongFieldUpdater( - Class tclass, String fieldName) { - if (hasUnsafe()) { - try { - return PlatformDependent0.newAtomicLongFieldUpdater(tclass, fieldName); - } catch (Throwable ignore) { - // ignore - } - } - return null; - } - - /** - * Create a new {@link Queue} which is safe to use for multiple producers (different threads) and a single - * consumer (one thread!). - */ - public static Queue newMpscQueue() { - return new MpscLinkedQueue(); - } - - /** - * Return the {@link ClassLoader} for the given {@link Class}. - */ - public static ClassLoader getClassLoader(final Class clazz) { - return PlatformDependent0.getClassLoader(clazz); - } - - /** - * Return the context {@link ClassLoader} for the current {@link Thread}. - */ - public static ClassLoader getContextClassLoader() { - return PlatformDependent0.getContextClassLoader(); - } - - /** - * Return the system {@link ClassLoader}. - */ - public static ClassLoader getSystemClassLoader() { - return PlatformDependent0.getSystemClassLoader(); - } - - private static boolean isAndroid0() { - boolean android; - try { - Class.forName("android.app.Application", false, getSystemClassLoader()); - android = true; - } catch (Exception e) { - // Failed to load the class uniquely available in Android. - android = false; - } - - if (android) { - logger.debug("Platform: Android"); - } - return android; - } - - private static boolean isWindows0() { - boolean windows = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).contains("win"); - if (windows) { - logger.debug("Platform: Windows"); - } - return windows; - } - - private static boolean isRoot0() { - if (isWindows()) { - return false; - } - - String[] ID_COMMANDS = { "/usr/bin/id", "/bin/id", "id", "/usr/xpg4/bin/id"}; - Pattern UID_PATTERN = Pattern.compile("^(?:0|[1-9][0-9]*)$"); - for (String idCmd: ID_COMMANDS) { - Process p = null; - BufferedReader in = null; - String uid = null; - try { - p = Runtime.getRuntime().exec(new String[] { idCmd, "-u" }); - in = new BufferedReader(new InputStreamReader(p.getInputStream(), CharsetUtil.US_ASCII)); - uid = in.readLine(); - in.close(); - - for (;;) { - try { - int exitCode = p.waitFor(); - if (exitCode != 0) { - uid = null; - } - break; - } catch (InterruptedException e) { - // Ignore - } - } - } catch (Exception e) { - // Failed to run the command. - uid = null; - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - // Ignore - } - } - if (p != null) { - try { - p.destroy(); - } catch (Exception e) { - // Android sometimes triggers an ErrnoException. - } - } - } - - if (uid != null && UID_PATTERN.matcher(uid).matches()) { - logger.debug("UID: {}", uid); - return "0".equals(uid); - } - } - - logger.debug("Could not determine the current UID using /usr/bin/id; attempting to bind at privileged ports."); - - Pattern PERMISSION_DENIED = Pattern.compile(".*(?:denied|not.*permitted).*"); - for (int i = 1023; i > 0; i --) { - ServerSocket ss = null; - try { - ss = new ServerSocket(); - ss.setReuseAddress(true); - ss.bind(new InetSocketAddress(i)); - if (logger.isDebugEnabled()) { - logger.debug("UID: 0 (succeded to bind at port {})", i); - } - return true; - } catch (Exception e) { - // Failed to bind. - // Check the error message so that we don't always need to bind 1023 times. - String message = e.getMessage(); - if (message == null) { - message = ""; - } - message = message.toLowerCase(); - if (PERMISSION_DENIED.matcher(message).matches()) { - break; - } - } finally { - if (ss != null) { - try { - ss.close(); - } catch (Exception e) { - // Ignore. - } - } - } - } - - logger.debug("UID: non-root (failed to bind at any privileged ports)"); - return false; - } - - - private static int javaVersion0() { - int javaVersion; - - // Not really a loop - for (;;) { - // Android - if (isAndroid()) { - javaVersion = 6; - break; - } - - try { - Class.forName("java.time.Clock", false, getClassLoader(Object.class)); - javaVersion = 8; - break; - } catch (Exception e) { - // Ignore - } - - try { - Class.forName("java.util.concurrent.LinkedTransferQueue", false, getClassLoader(BlockingQueue.class)); - javaVersion = 7; - break; - } catch (Exception e) { - // Ignore - } - - javaVersion = 6; - break; - } - - if (logger.isDebugEnabled()) { - logger.debug("Java version: {}", javaVersion); - } - return javaVersion; - } - - private static boolean hasUnsafe0() { - boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false); - logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe); - - if (isAndroid()) { - logger.debug("sun.misc.Unsafe: unavailable (Android)"); - return false; - } - - if (noUnsafe) { - logger.debug("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)"); - return false; - } - - // Legacy properties - boolean tryUnsafe; - if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) { - tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true); - } else { - tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true); - } - - if (!tryUnsafe) { - logger.debug("sun.misc.Unsafe: unavailable (io.netty.tryUnsafe/org.jboss.netty.tryUnsafe)"); - return false; - } - - try { - boolean hasUnsafe = PlatformDependent0.hasUnsafe(); - logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable"); - return hasUnsafe; - } catch (Throwable t) { - // Probably failed to initialize PlatformDependent0. - return false; - } - } - - private static long arrayBaseOffset0() { - if (!hasUnsafe()) { - return -1; - } - - return PlatformDependent0.arrayBaseOffset(); - } - - private static long maxDirectMemory0() { - long maxDirectMemory = 0; - try { - // Try to get from sun.misc.VM.maxDirectMemory() which should be most accurate. - Class vmClass = Class.forName("sun.misc.VM", true, getSystemClassLoader()); - Method m = vmClass.getDeclaredMethod("maxDirectMemory"); - maxDirectMemory = ((Number) m.invoke(null)).longValue(); - } catch (Throwable t) { - // Ignore - } - - if (maxDirectMemory > 0) { - return maxDirectMemory; - } - - try { - // Now try to get the JVM option (-XX:MaxDirectMemorySize) and parse it. - // Note that we are using reflection because Android doesn't have these classes. - Class mgmtFactoryClass = Class.forName( - "java.lang.management.ManagementFactory", true, getSystemClassLoader()); - Class runtimeClass = Class.forName( - "java.lang.management.RuntimeMXBean", true, getSystemClassLoader()); - - Object runtime = mgmtFactoryClass.getDeclaredMethod("getRuntimeMXBean").invoke(null); - - - List vmArgs = (List) runtimeClass.getDeclaredMethod("getInputArguments").invoke(runtime); - for (int i = vmArgs.size() - 1; i >= 0; i --) { - Matcher m = MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN.matcher(vmArgs.get(i)); - if (!m.matches()) { - continue; - } - - maxDirectMemory = Long.parseLong(m.group(1)); - switch (m.group(2).charAt(0)) { - case 'k': case 'K': - maxDirectMemory *= 1024; - break; - case 'm': case 'M': - maxDirectMemory *= 1024 * 1024; - break; - case 'g': case 'G': - maxDirectMemory *= 1024 * 1024 * 1024; - break; - } - break; - } - } catch (Throwable t) { - // Ignore - } - - if (maxDirectMemory <= 0) { - maxDirectMemory = Runtime.getRuntime().maxMemory(); - logger.debug("maxDirectMemory: {} bytes (maybe)", maxDirectMemory); - } else { - logger.debug("maxDirectMemory: {} bytes", maxDirectMemory); - } - - return maxDirectMemory; - } - -// private static boolean hasJavassist0() { -// if (isAndroid()) { -// return false; -// } -// -// boolean noJavassist = SystemPropertyUtil.getBoolean("io.netty.noJavassist", false); -// logger.debug("-Dio.netty.noJavassist: {}", noJavassist); -// -// if (noJavassist) { -// logger.debug("Javassist: unavailable (io.netty.noJavassist)"); -// return false; -// } -// -// try { -// JavassistTypeParameterMatcherGenerator.generate(Object.class, getClassLoader(PlatformDependent.class)); -// logger.debug("Javassist: available"); -// return true; -// } catch (Throwable t) { -// // Failed to generate a Javassist-based matcher. -// logger.debug("Javassist: unavailable"); -// logger.debug( -// "You don't have Javassist in your class path or you don't have enough permission " + -// "to load dynamically generated classes. Please check the configuration for better performance."); -// return false; -// } -// } - -// private static File tmpdir0() { -// File f; -// try { -// f = toDirectory(SystemPropertyUtil.get("io.netty.tmpdir")); -// if (f != null) { -// logger.debug("-Dio.netty.tmpdir: {}", f); -// return f; -// } -// -// f = toDirectory(SystemPropertyUtil.get("java.io.tmpdir")); -// if (f != null) { -// logger.debug("-Dio.netty.tmpdir: {} (java.io.tmpdir)", f); -// return f; -// } -// -// // This shouldn't happen, but just in case .. -// if (isWindows()) { -// f = toDirectory(System.getenv("TEMP")); -// if (f != null) { -// logger.debug("-Dio.netty.tmpdir: {} (%TEMP%)", f); -// return f; -// } -// -// String userprofile = System.getenv("USERPROFILE"); -// if (userprofile != null) { -// f = toDirectory(userprofile + "\\AppData\\Local\\Temp"); -// if (f != null) { -// logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\AppData\\Local\\Temp)", f); -// return f; -// } -// -// f = toDirectory(userprofile + "\\Local Settings\\Temp"); -// if (f != null) { -// logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\Local Settings\\Temp)", f); -// return f; -// } -// } -// } else { -// f = toDirectory(System.getenv("TMPDIR")); -// if (f != null) { -// logger.debug("-Dio.netty.tmpdir: {} ($TMPDIR)", f); -// return f; -// } -// } -// } catch (Exception ignored) { -// // Environment variable inaccessible -// } -// -// // Last resort. -// if (isWindows()) { -// f = new File("C:\\Windows\\Temp"); -// } else { -// f = new File("/tmp"); -// } -// -// logger.warn("Failed to get the temporary directory; falling back to: {}", f); -// return f; -// } -// -// -// private static File toDirectory(String path) { -// if (path == null) { -// return null; -// } -// -// File f = new File(path); -// f.mkdirs(); -// -// if (!f.isDirectory()) { -// return null; -// } -// -// try { -// return f.getAbsoluteFile(); -// } catch (Exception ignored) { -// return f; -// } -// } - -// private static int bitMode0() { -// // Check user-specified bit mode first. -// int bitMode = SystemPropertyUtil.getInt("io.netty.bitMode", 0); -// if (bitMode > 0) { -// logger.debug("-Dio.netty.bitMode: {}", bitMode); -// return bitMode; -// } -// -// // And then the vendor specific ones which is probably most reliable. -// bitMode = SystemPropertyUtil.getInt("sun.arch.data.model", 0); -// if (bitMode > 0) { -// logger.debug("-Dio.netty.bitMode: {} (sun.arch.data.model)", bitMode); -// return bitMode; -// } -// bitMode = SystemPropertyUtil.getInt("com.ibm.vm.bitmode", 0); -// if (bitMode > 0) { -// logger.debug("-Dio.netty.bitMode: {} (com.ibm.vm.bitmode)", bitMode); -// return bitMode; -// } -// -// // os.arch also gives us a good hint. -// String arch = SystemPropertyUtil.get("os.arch", "").toLowerCase(Locale.US).trim(); -// if ("amd64".equals(arch) || "x86_64".equals(arch)) { -// bitMode = 64; -// } else if ("i386".equals(arch) || "i486".equals(arch) || "i586".equals(arch) || "i686".equals(arch)) { -// bitMode = 32; -// } -// -// if (bitMode > 0) { -// logger.debug("-Dio.netty.bitMode: {} (os.arch: {})", bitMode, arch); -// } -// -// // Last resort: guess from VM name and then fall back to most common 64-bit mode. -// String vm = SystemPropertyUtil.get("java.vm.name", "").toLowerCase(Locale.US); -// Pattern BIT_PATTERN = Pattern.compile("([1-9][0-9]+)-?bit"); -// Matcher m = BIT_PATTERN.matcher(vm); -// if (m.find()) { -// return Integer.parseInt(m.group(1)); -// } else { -// return 64; -// } -// } - -// private static int addressSize0() { -// if (!hasUnsafe()) { -// return -1; -// } -// return PlatformDependent0.addressSize(); -// } - - private PlatformDependent() { - // only static method supported - } -} diff --git a/java/src/game/net/util/internal/PlatformDependent0.java b/java/src/game/net/util/internal/PlatformDependent0.java deleted file mode 100644 index 8f01dc0..0000000 --- a/java/src/game/net/util/internal/PlatformDependent0.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; -import sun.misc.Unsafe; - -/** - * The {@link PlatformDependent} operations which requires access to {@code sun.misc.*}. - */ -final class PlatformDependent0 { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent0.class); - private static final Unsafe UNSAFE; - private static final boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - private static final long ADDRESS_FIELD_OFFSET; - - /** - * Limits the number of bytes to copy per {@link Unsafe#copyMemory(long, long, long)} to allow safepoint polling - * during a large copy. - */ - private static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L; - - /** - * {@code true} if and only if the platform supports unaligned access. - * - * @see Wikipedia on segfault - */ - private static final boolean UNALIGNED; - - static { - ByteBuffer direct = ByteBuffer.allocateDirect(1); - Field addressField; - try { - addressField = Buffer.class.getDeclaredField("address"); - addressField.setAccessible(true); - if (addressField.getLong(ByteBuffer.allocate(1)) != 0) { - // A heap buffer must have 0 address. - addressField = null; - } else { - if (addressField.getLong(direct) == 0) { - // A direct buffer must have non-zero address. - addressField = null; - } - } - } catch (Throwable t) { - // Failed to access the address field. - addressField = null; - } - logger.debug("java.nio.Buffer.address: {}", addressField != null? "available" : "unavailable"); - - Unsafe unsafe; - if (addressField != null) { - try { - Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - unsafe = (Unsafe) unsafeField.get(null); - logger.debug("sun.misc.Unsafe.theUnsafe: {}", unsafe != null ? "available" : "unavailable"); - - // Ensure the unsafe supports all necessary methods to work around the mistake in the latest OpenJDK. - // https://github.com/netty/netty/issues/1061 - // http://www.mail-archive.com/jdk6-dev@openjdk.java.net/msg00698.html - try { - if (unsafe != null) { - unsafe.getClass().getDeclaredMethod( - "copyMemory", Object.class, long.class, Object.class, long.class, long.class); - logger.debug("sun.misc.Unsafe.copyMemory: available"); - } - } catch (NoSuchMethodError t) { - logger.debug("sun.misc.Unsafe.copyMemory: unavailable"); - throw t; - } catch (NoSuchMethodException e) { - logger.debug("sun.misc.Unsafe.copyMemory: unavailable"); - throw e; - } - } catch (Throwable cause) { - // Unsafe.copyMemory(Object, long, Object, long, long) unavailable. - unsafe = null; - } - } else { - // If we cannot access the address of a direct buffer, there's no point of using unsafe. - // Let's just pretend unsafe is unavailable for overall simplicity. - unsafe = null; - } - - UNSAFE = unsafe; - - if (unsafe == null) { - ADDRESS_FIELD_OFFSET = -1; - UNALIGNED = false; - } else { - ADDRESS_FIELD_OFFSET = objectFieldOffset(addressField); - boolean unaligned; - try { - Class bitsClass = Class.forName("java.nio.Bits", false, ClassLoader.getSystemClassLoader()); - Method unalignedMethod = bitsClass.getDeclaredMethod("unaligned"); - unalignedMethod.setAccessible(true); - unaligned = Boolean.TRUE.equals(unalignedMethod.invoke(null)); - } catch (Throwable t) { - // We at least know x86 and x64 support unaligned access. - String arch = SystemPropertyUtil.get("os.arch", ""); - //noinspection DynamicRegexReplaceableByCompiledPattern - unaligned = arch.matches("^(i[3-6]86|x86(_64)?|x64|amd64)$"); - } - - UNALIGNED = unaligned; - logger.debug("java.nio.Bits.unaligned: {}", UNALIGNED); - } - } - - static boolean hasUnsafe() { - return UNSAFE != null; - } - - static void throwException(Throwable t) { - UNSAFE.throwException(t); - } - - static void freeDirectBuffer(ByteBuffer buffer) { - // Delegate to other class to not break on android - // See https://github.com/netty/netty/issues/2604 - Cleaner0.freeDirectBuffer(buffer); - } - - static long directBufferAddress(ByteBuffer buffer) { - return getLong(buffer, ADDRESS_FIELD_OFFSET); - } - - static long arrayBaseOffset() { - return UNSAFE.arrayBaseOffset(byte[].class); - } - - static Object getObject(Object object, long fieldOffset) { - return UNSAFE.getObject(object, fieldOffset); - } - - static Object getObjectVolatile(Object object, long fieldOffset) { - return UNSAFE.getObjectVolatile(object, fieldOffset); - } - - static int getInt(Object object, long fieldOffset) { - return UNSAFE.getInt(object, fieldOffset); - } - - private static long getLong(Object object, long fieldOffset) { - return UNSAFE.getLong(object, fieldOffset); - } - - static long objectFieldOffset(Field field) { - return UNSAFE.objectFieldOffset(field); - } - - static byte getByte(long address) { - return UNSAFE.getByte(address); - } - - static short getShort(long address) { - if (UNALIGNED) { - return UNSAFE.getShort(address); - } else if (BIG_ENDIAN) { - return (short) (getByte(address) << 8 | getByte(address + 1) & 0xff); - } else { - return (short) (getByte(address + 1) << 8 | getByte(address) & 0xff); - } - } - - static int getInt(long address) { - if (UNALIGNED) { - return UNSAFE.getInt(address); - } else if (BIG_ENDIAN) { - return getByte(address) << 24 | - (getByte(address + 1) & 0xff) << 16 | - (getByte(address + 2) & 0xff) << 8 | - getByte(address + 3) & 0xff; - } else { - return getByte(address + 3) << 24 | - (getByte(address + 2) & 0xff) << 16 | - (getByte(address + 1) & 0xff) << 8 | - getByte(address) & 0xff; - } - } - - static long getLong(long address) { - if (UNALIGNED) { - return UNSAFE.getLong(address); - } else if (BIG_ENDIAN) { - return (long) getByte(address) << 56 | - ((long) getByte(address + 1) & 0xff) << 48 | - ((long) getByte(address + 2) & 0xff) << 40 | - ((long) getByte(address + 3) & 0xff) << 32 | - ((long) getByte(address + 4) & 0xff) << 24 | - ((long) getByte(address + 5) & 0xff) << 16 | - ((long) getByte(address + 6) & 0xff) << 8 | - (long) getByte(address + 7) & 0xff; - } else { - return (long) getByte(address + 7) << 56 | - ((long) getByte(address + 6) & 0xff) << 48 | - ((long) getByte(address + 5) & 0xff) << 40 | - ((long) getByte(address + 4) & 0xff) << 32 | - ((long) getByte(address + 3) & 0xff) << 24 | - ((long) getByte(address + 2) & 0xff) << 16 | - ((long) getByte(address + 1) & 0xff) << 8 | - (long) getByte(address) & 0xff; - } - } - - static void putOrderedObject(Object object, long address, Object value) { - UNSAFE.putOrderedObject(object, address, value); - } - - static void putByte(long address, byte value) { - UNSAFE.putByte(address, value); - } - - static void putShort(long address, short value) { - if (UNALIGNED) { - UNSAFE.putShort(address, value); - } else if (BIG_ENDIAN) { - putByte(address, (byte) (value >>> 8)); - putByte(address + 1, (byte) value); - } else { - putByte(address + 1, (byte) (value >>> 8)); - putByte(address, (byte) value); - } - } - - static void putInt(long address, int value) { - if (UNALIGNED) { - UNSAFE.putInt(address, value); - } else if (BIG_ENDIAN) { - putByte(address, (byte) (value >>> 24)); - putByte(address + 1, (byte) (value >>> 16)); - putByte(address + 2, (byte) (value >>> 8)); - putByte(address + 3, (byte) value); - } else { - putByte(address + 3, (byte) (value >>> 24)); - putByte(address + 2, (byte) (value >>> 16)); - putByte(address + 1, (byte) (value >>> 8)); - putByte(address, (byte) value); - } - } - - static void putLong(long address, long value) { - if (UNALIGNED) { - UNSAFE.putLong(address, value); - } else if (BIG_ENDIAN) { - putByte(address, (byte) (value >>> 56)); - putByte(address + 1, (byte) (value >>> 48)); - putByte(address + 2, (byte) (value >>> 40)); - putByte(address + 3, (byte) (value >>> 32)); - putByte(address + 4, (byte) (value >>> 24)); - putByte(address + 5, (byte) (value >>> 16)); - putByte(address + 6, (byte) (value >>> 8)); - putByte(address + 7, (byte) value); - } else { - putByte(address + 7, (byte) (value >>> 56)); - putByte(address + 6, (byte) (value >>> 48)); - putByte(address + 5, (byte) (value >>> 40)); - putByte(address + 4, (byte) (value >>> 32)); - putByte(address + 3, (byte) (value >>> 24)); - putByte(address + 2, (byte) (value >>> 16)); - putByte(address + 1, (byte) (value >>> 8)); - putByte(address, (byte) value); - } - } - - static void copyMemory(long srcAddr, long dstAddr, long length) { - //UNSAFE.copyMemory(srcAddr, dstAddr, length); - while (length > 0) { - long size = Math.min(length, UNSAFE_COPY_THRESHOLD); - UNSAFE.copyMemory(srcAddr, dstAddr, size); - length -= size; - srcAddr += size; - dstAddr += size; - } - } - - static void copyMemory(Object src, long srcOffset, Object dst, long dstOffset, long length) { - //UNSAFE.copyMemory(src, srcOffset, dst, dstOffset, length); - while (length > 0) { - long size = Math.min(length, UNSAFE_COPY_THRESHOLD); - UNSAFE.copyMemory(src, srcOffset, dst, dstOffset, size); - length -= size; - srcOffset += size; - dstOffset += size; - } - } - - static AtomicReferenceFieldUpdater newAtomicReferenceFieldUpdater( - Class tclass, String fieldName) throws Exception { - return new UnsafeAtomicReferenceFieldUpdater(UNSAFE, tclass, fieldName); - } - - static AtomicIntegerFieldUpdater newAtomicIntegerFieldUpdater( - Class tclass, String fieldName) throws Exception { - return new UnsafeAtomicIntegerFieldUpdater(UNSAFE, tclass, fieldName); - } - - static AtomicLongFieldUpdater newAtomicLongFieldUpdater( - Class tclass, String fieldName) throws Exception { - return new UnsafeAtomicLongFieldUpdater(UNSAFE, tclass, fieldName); - } - - static ClassLoader getClassLoader(final Class clazz) { - if (System.getSecurityManager() == null) { - return clazz.getClassLoader(); - } else { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return clazz.getClassLoader(); - } - }); - } - } - - static ClassLoader getContextClassLoader() { - if (System.getSecurityManager() == null) { - return Thread.currentThread().getContextClassLoader(); - } else { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return Thread.currentThread().getContextClassLoader(); - } - }); - } - } - - static ClassLoader getSystemClassLoader() { - if (System.getSecurityManager() == null) { - return ClassLoader.getSystemClassLoader(); - } else { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return ClassLoader.getSystemClassLoader(); - } - }); - } - } - - static int addressSize() { - return UNSAFE.addressSize(); - } - - static long allocateMemory(long size) { - return UNSAFE.allocateMemory(size); - } - - static void freeMemory(long address) { - UNSAFE.freeMemory(address); - } - - private PlatformDependent0() { - } - -} diff --git a/java/src/game/net/util/internal/RecyclableArrayList.java b/java/src/game/net/util/internal/RecyclableArrayList.java deleted file mode 100644 index 04f2385..0000000 --- a/java/src/game/net/util/internal/RecyclableArrayList.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.RandomAccess; - -import game.net.util.Recycler; -import game.net.util.Recycler.Handle; - -/** - * A simple list which is reyclable. This implementation does not allow {@code null} elements to be added. - */ -public final class RecyclableArrayList extends ArrayList { - - private static final long serialVersionUID = -8605125654176467947L; - - private static final int DEFAULT_INITIAL_CAPACITY = 8; - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected RecyclableArrayList newObject(Handle handle) { - return new RecyclableArrayList(handle); - } - }; - - /** - * Create a new empty {@link RecyclableArrayList} instance - */ - public static RecyclableArrayList newInstance() { - return newInstance(DEFAULT_INITIAL_CAPACITY); - } - - /** - * Create a new empty {@link RecyclableArrayList} instance with the given capacity. - */ - public static RecyclableArrayList newInstance(int minCapacity) { - RecyclableArrayList ret = RECYCLER.get(); - ret.ensureCapacity(minCapacity); - return ret; - } - - private final Handle handle; - - private RecyclableArrayList(Handle handle) { - this(handle, DEFAULT_INITIAL_CAPACITY); - } - - private RecyclableArrayList(Handle handle, int initialCapacity) { - super(initialCapacity); - this.handle = handle; - } - - @Override - public boolean addAll(Collection c) { - checkNullElements(c); - return super.addAll(c); - } - - @Override - public boolean addAll(int index, Collection c) { - checkNullElements(c); - return super.addAll(index, c); - } - - private static void checkNullElements(Collection c) { - if (c instanceof RandomAccess && c instanceof List) { - // produce less garbage - List list = (List) c; - int size = list.size(); - for (int i = 0; i < size; i++) { - if (list.get(i) == null) { - throw new IllegalArgumentException("c contains null values"); - } - } - } else { - for (Object element: c) { - if (element == null) { - throw new IllegalArgumentException("c contains null values"); - } - } - } - } - - @Override - public boolean add(Object element) { - if (element == null) { - throw new NullPointerException("element"); - } - return super.add(element); - } - - @Override - public void add(int index, Object element) { - if (element == null) { - throw new NullPointerException("element"); - } - super.add(index, element); - } - - @Override - public Object set(int index, Object element) { - if (element == null) { - throw new NullPointerException("element"); - } - return super.set(index, element); - } - - /** - * Clear and recycle this instance. - */ - public boolean recycle() { - clear(); - return RECYCLER.recycle(this, handle); - } -} diff --git a/java/src/game/net/util/internal/RecyclableMpscLinkedQueueNode.java b/java/src/game/net/util/internal/RecyclableMpscLinkedQueueNode.java deleted file mode 100644 index 46cd00a..0000000 --- a/java/src/game/net/util/internal/RecyclableMpscLinkedQueueNode.java +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ - -package game.net.util.internal; - -import game.net.util.Recycler; - -/** - * {@link MpscLinkedQueueNode} that will automatically call {@link #recycle(Recycler.Handle)} when the node was - * unlinked. - */ -public abstract class RecyclableMpscLinkedQueueNode extends MpscLinkedQueueNode { - private final Recycler.Handle handle; - - protected RecyclableMpscLinkedQueueNode(Recycler.Handle handle) { - if (handle == null) { - throw new NullPointerException("handle"); - } - this.handle = handle; - } - - @Override - final void unlink() { - super.unlink(); - recycle(handle); - } - - /** - * Called once unliked and so ready to recycled. - */ - protected abstract void recycle(Recycler.Handle handle); -} diff --git a/java/src/game/net/util/internal/StringUtil.java b/java/src/game/net/util/internal/StringUtil.java deleted file mode 100644 index f86ba73..0000000 --- a/java/src/game/net/util/internal/StringUtil.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Formatter; -import java.util.List; - -/** - * String utility class. - */ -public final class StringUtil { - - public static final String NEWLINE; - - private static final String[] BYTE2HEX_PAD = new String[256]; - private static final String[] BYTE2HEX_NOPAD = new String[256]; - private static final String EMPTY_STRING = ""; - - static { - // Determine the newline character of the current platform. - String newLine; - Formatter formatter = null; - - try { - formatter = new Formatter(); - newLine = formatter.format("%n").toString(); - } catch (Exception e) { - // Should not reach here, but just in case. - newLine = "\n"; - } - finally { - if(formatter != null) { - try { - formatter.close(); - } - catch(Throwable e) { - } - } - } - - NEWLINE = newLine; - - // Generate the lookup table that converts a byte into a 2-digit hexadecimal integer. - int i; - for (i = 0; i < 10; i ++) { - StringBuilder buf = new StringBuilder(2); - buf.append('0'); - buf.append(i); - BYTE2HEX_PAD[i] = buf.toString(); - BYTE2HEX_NOPAD[i] = String.valueOf(i); - } - for (; i < 16; i ++) { - StringBuilder buf = new StringBuilder(2); - char c = (char) ('a' + i - 10); - buf.append('0'); - buf.append(c); - BYTE2HEX_PAD[i] = buf.toString(); - BYTE2HEX_NOPAD[i] = String.valueOf(c); - } - for (; i < BYTE2HEX_PAD.length; i ++) { - StringBuilder buf = new StringBuilder(2); - buf.append(Integer.toHexString(i)); - String str = buf.toString(); - BYTE2HEX_PAD[i] = str; - BYTE2HEX_NOPAD[i] = str; - } - } - - /** - * Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized - * version of {@link String#split(String)}. - */ - public static String[] split(String value, char delim) { - final int end = value.length(); - final List res = new ArrayList(); - - int start = 0; - for (int i = 0; i < end; i ++) { - if (value.charAt(i) == delim) { - if (start == i) { - res.add(EMPTY_STRING); - } else { - res.add(value.substring(start, i)); - } - start = i + 1; - } - } - - if (start == 0) { // If no delimiter was found in the value - res.add(value); - } else { - if (start != end) { - // Add the last element if it's not empty. - res.add(value.substring(start, end)); - } else { - // Truncate trailing empty elements. - for (int i = res.size() - 1; i >= 0; i --) { - if (res.get(i).isEmpty()) { - res.remove(i); - } else { - break; - } - } - } - } - - return res.toArray(new String[res.size()]); - } - - /** - * Converts the specified byte value into a 2-digit hexadecimal integer. - */ - public static String byteToHexStringPadded(int value) { - return BYTE2HEX_PAD[value & 0xff]; - } - - /** - * Converts the specified byte value into a 2-digit hexadecimal integer and appends it to the specified buffer. - */ - public static T byteToHexStringPadded(T buf, int value) { - try { - buf.append(byteToHexStringPadded(value)); - } catch (IOException e) { - PlatformDependent.throwException(e); - } - return buf; - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexStringPadded(byte[] src) { - return toHexStringPadded(src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexStringPadded(byte[] src, int offset, int length) { - return toHexStringPadded(new StringBuilder(length << 1), src, offset, length).toString(); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexStringPadded(T dst, byte[] src) { - return toHexStringPadded(dst, src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexStringPadded(T dst, byte[] src, int offset, int length) { - final int end = offset + length; - for (int i = offset; i < end; i ++) { - byteToHexStringPadded(dst, src[i]); - } - return dst; - } - - /** - * Converts the specified byte value into a hexadecimal integer. - */ - public static String byteToHexString(int value) { - return BYTE2HEX_NOPAD[value & 0xff]; - } - - /** - * Converts the specified byte value into a hexadecimal integer and appends it to the specified buffer. - */ - public static T byteToHexString(T buf, int value) { - try { - buf.append(byteToHexString(value)); - } catch (IOException e) { - PlatformDependent.throwException(e); - } - return buf; - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexString(byte[] src) { - return toHexString(src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexString(byte[] src, int offset, int length) { - return toHexString(new StringBuilder(length << 1), src, offset, length).toString(); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexString(T dst, byte[] src) { - return toHexString(dst, src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexString(T dst, byte[] src, int offset, int length) { - assert length >= 0; - if (length == 0) { - return dst; - } - - final int end = offset + length; - final int endMinusOne = end - 1; - int i; - - // Skip preceding zeroes. - for (i = offset; i < endMinusOne; i ++) { - if (src[i] != 0) { - break; - } - } - - byteToHexString(dst, src[i ++]); - int remaining = end - i; - toHexStringPadded(dst, src, i, remaining); - - return dst; - } - - /** - * The shortcut to {@link #simpleClassName(Class) simpleClassName(o.getClass())}. - */ - public static String simpleClassName(Object o) { - if (o == null) { - return "null_object"; - } else { - return simpleClassName(o.getClass()); - } - } - - /** - * Generates a simplified name from a {@link Class}. Similar to {@link Class#getSimpleName()}, but it works fine - * with anonymous classes. - */ - public static String simpleClassName(Class clazz) { - if (clazz == null) { - return "null_class"; - } - - Package pkg = clazz.getPackage(); - if (pkg != null) { - return clazz.getName().substring(pkg.getName().length() + 1); - } else { - return clazz.getName(); - } - } - - private StringUtil() { - // Unused. - } -} diff --git a/java/src/game/net/util/internal/SystemPropertyUtil.java b/java/src/game/net/util/internal/SystemPropertyUtil.java deleted file mode 100644 index 6ed2d8c..0000000 --- a/java/src/game/net/util/internal/SystemPropertyUtil.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Pattern; - -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A collection of utility methods to retrieve and parse the values of the Java system properties. - */ -public final class SystemPropertyUtil { - - private static boolean initializedLogger; - private static final InternalLogger logger; - private static boolean loggedException; - - static { - initializedLogger = false; - logger = InternalLoggerFactory.getInstance(SystemPropertyUtil.class); - initializedLogger = true; - } - - /** - * Returns {@code true} if and only if the system property with the specified {@code key} - * exists. - */ - public static boolean contains(String key) { - return get(key) != null; - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to {@code null} if the property access fails. - * - * @return the property value or {@code null} - */ - public static String get(String key) { - return get(key, null); - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static String get(final String key, String def) { - if (key == null) { - throw new NullPointerException("key"); - } - if (key.isEmpty()) { - throw new IllegalArgumentException("key must not be empty."); - } - - String value = null; - try { - if (System.getSecurityManager() == null) { - value = System.getProperty(key); - } else { - value = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public String run() { - return System.getProperty(key); - } - }); - } - } catch (Exception e) { - if (!loggedException) { - log("Unable to retrieve a system property '" + key + "'; default values will be used.", e); - loggedException = true; - } - } - - if (value == null) { - return def; - } - - return value; - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static boolean getBoolean(String key, boolean def) { - String value = get(key); - if (value == null) { - return def; - } - - value = value.trim().toLowerCase(); - if (value.isEmpty()) { - return true; - } - - if ("true".equals(value) || "yes".equals(value) || "1".equals(value)) { - return true; - } - - if ("false".equals(value) || "no".equals(value) || "0".equals(value)) { - return false; - } - - log( - "Unable to parse the boolean system property '" + key + "':" + value + " - " + - "using the default value: " + def); - - return def; - } - - private static final Pattern INTEGER_PATTERN = Pattern.compile("-?[0-9]+"); - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static int getInt(String key, int def) { - String value = get(key); - if (value == null) { - return def; - } - - value = value.trim().toLowerCase(); - if (INTEGER_PATTERN.matcher(value).matches()) { - try { - return Integer.parseInt(value); - } catch (Exception e) { - // Ignore - } - } - - log( - "Unable to parse the integer system property '" + key + "':" + value + " - " + - "using the default value: " + def); - - return def; - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static long getLong(String key, long def) { - String value = get(key); - if (value == null) { - return def; - } - - value = value.trim().toLowerCase(); - if (INTEGER_PATTERN.matcher(value).matches()) { - try { - return Long.parseLong(value); - } catch (Exception e) { - // Ignore - } - } - - log( - "Unable to parse the long integer system property '" + key + "':" + value + " - " + - "using the default value: " + def); - - return def; - } - - private static void log(String msg) { - if (initializedLogger) { - logger.warn(msg); - } else { - // Use JDK logging if logger was not initialized yet. - Logger.getLogger(SystemPropertyUtil.class.getName()).log(Level.WARNING, msg); - } - } - - private static void log(String msg, Exception e) { - if (initializedLogger) { - logger.warn(msg, e); - } else { - // Use JDK logging if logger was not initialized yet. - Logger.getLogger(SystemPropertyUtil.class.getName()).log(Level.WARNING, msg, e); - } - } - - private SystemPropertyUtil() { - // Unused - } -} diff --git a/java/src/game/net/util/internal/ThreadLocalRandom.java b/java/src/game/net/util/internal/ThreadLocalRandom.java deleted file mode 100644 index e9ac4d0..0000000 --- a/java/src/game/net/util/internal/ThreadLocalRandom.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -package game.net.util.internal; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.security.SecureRandom; -import java.util.Random; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import game.net.util.internal.logging.InternalLogger; -import game.net.util.internal.logging.InternalLoggerFactory; - -/** - * A random number generator isolated to the current thread. Like the - * global {@link java.util.Random} generator used by the {@link - * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized - * with an internally generated seed that may not otherwise be - * modified. When applicable, use of {@code ThreadLocalRandom} rather - * than shared {@code Random} objects in concurrent programs will - * typically encounter much less overhead and contention. Use of - * {@code ThreadLocalRandom} is particularly appropriate when multiple - * tasks (for example, each a {@link io.netty.util.internal.chmv8.ForkJoinTask}) use random numbers - * in parallel in thread pools. - * - *

Usages of this class should typically be of the form: - * {@code ThreadLocalRandom.current().nextX(...)} (where - * {@code X} is {@code Int}, {@code Long}, etc). - * When all usages are of this form, it is never possible to - * accidently share a {@code ThreadLocalRandom} across multiple threads. - * - *

This class also provides additional commonly used bounded random - * generation methods. - * - * //since 1.7 - * //author Doug Lea - */ - -public final class ThreadLocalRandom extends Random { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ThreadLocalRandom.class); - - private static final AtomicLong seedUniquifier = new AtomicLong(); - - private static volatile long initialSeedUniquifier; - - public static void setInitialSeedUniquifier(long initialSeedUniquifier) { - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier; - } - - public static synchronized long getInitialSeedUniquifier() { - // Use the value set via the setter. - long initialSeedUniquifier = ThreadLocalRandom.initialSeedUniquifier; - if (initialSeedUniquifier == 0) { - // Use the system property value. - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier = - SystemPropertyUtil.getLong("io.netty.initialSeedUniquifier", 0); - } - - // Otherwise, generate one. - if (initialSeedUniquifier == 0) { - // Try to generate a real random number from /dev/random. - // Get from a different thread to avoid blocking indefinitely on a machine without much entrophy. - final BlockingQueue queue = new LinkedBlockingQueue(); - Thread generatorThread = new Thread("initialSeedUniquifierGenerator") { - @Override - public void run() { - SecureRandom random = new SecureRandom(); // Get the real random seed from /dev/random - queue.add(random.generateSeed(8)); - } - }; - generatorThread.setDaemon(true); - generatorThread.start(); - generatorThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - logger.debug("An exception has been raised by {}", t.getName(), e); - } - }); - - // Get the random seed from the thread with timeout. - final long timeoutSeconds = 3; - final long deadLine = System.nanoTime() + TimeUnit.SECONDS.toNanos(timeoutSeconds); - boolean interrupted = false; - for (;;) { - long waitTime = deadLine - System.nanoTime(); - if (waitTime <= 0) { - generatorThread.interrupt(); - logger.warn( - "Failed to generate a seed from SecureRandom within {} seconds. " + - "Not enough entrophy?", timeoutSeconds - ); - break; - } - - try { - byte[] seed = queue.poll(waitTime, TimeUnit.NANOSECONDS); - if (seed != null) { - initialSeedUniquifier = - ((long) seed[0] & 0xff) << 56 | - ((long) seed[1] & 0xff) << 48 | - ((long) seed[2] & 0xff) << 40 | - ((long) seed[3] & 0xff) << 32 | - ((long) seed[4] & 0xff) << 24 | - ((long) seed[5] & 0xff) << 16 | - ((long) seed[6] & 0xff) << 8 | - (long) seed[7] & 0xff; - break; - } - } catch (InterruptedException e) { - interrupted = true; - logger.warn("Failed to generate a seed from SecureRandom due to an InterruptedException."); - break; - } - } - - // Just in case the initialSeedUniquifier is zero or some other constant - initialSeedUniquifier ^= 0x3255ecdc33bae119L; // just a meaningless random number - initialSeedUniquifier ^= Long.reverse(System.nanoTime()); - - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier; - - if (interrupted) { - // Restore the interrupt status because we don't know how to/don't need to handle it here. - Thread.currentThread().interrupt(); - - // Interrupt the generator thread if it's still running, - // in the hope that the SecureRandom provider raises an exception on interruption. - generatorThread.interrupt(); - } - } - - return initialSeedUniquifier; - } - - private static long newSeed() { - final long startTime = System.nanoTime(); - for (;;) { - final long current = seedUniquifier.get(); - final long actualCurrent = current != 0? current : getInitialSeedUniquifier(); - - // L'Ecuyer, "Tables of Linear Congruential Generators of Different Sizes and Good Lattice Structure", 1999 - final long next = actualCurrent * 181783497276652981L; - - if (seedUniquifier.compareAndSet(current, next)) { - if (current == 0 && logger.isDebugEnabled()) { - logger.debug(String.format( - "-Dio.netty.initialSeedUniquifier: 0x%016x (took %d ms)", - actualCurrent, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime))); - } - return next ^ System.nanoTime(); - } - } - } - - // same constants as Random, but must be redeclared because private - private static final long multiplier = 0x5DEECE66DL; - private static final long addend = 0xBL; - private static final long mask = (1L << 48) - 1; - - /** - * The random seed. We can't use super.seed. - */ - private long rnd; - - /** - * Initialization flag to permit calls to setSeed to succeed only - * while executing the Random constructor. We can't allow others - * since it would cause setting seed in one part of a program to - * unintentionally impact other usages by the thread. - */ - boolean initialized; - - // Padding to help avoid memory contention among seed updates in - // different TLRs in the common case that they are located near - // each other. - private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - /** - * Constructor called only by localRandom.initialValue. - */ - ThreadLocalRandom() { - super(newSeed()); - initialized = true; - } - - /** - * Returns the current thread's {@code ThreadLocalRandom}. - * - * @return the current thread's {@code ThreadLocalRandom} - */ - public static ThreadLocalRandom current() { - return InternalThreadLocalMap.get().random(); - } - - /** - * Throws {@code UnsupportedOperationException}. Setting seeds in - * this generator is not supported. - * - * @throws UnsupportedOperationException always - */ - public void setSeed(long seed) { - if (initialized) { - throw new UnsupportedOperationException(); - } - rnd = (seed ^ multiplier) & mask; - } - - protected int next(int bits) { - rnd = (rnd * multiplier + addend) & mask; - return (int) (rnd >>> (48 - bits)); - } - - /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). - * - * @param least the least value returned - * @param bound the upper bound (exclusive) - * @throws IllegalArgumentException if least greater than or equal - * to bound - * @return the next value - */ - public int nextInt(int least, int bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextInt(bound - least) + least; - } - - /** - * Returns a pseudorandom, uniformly distributed value - * between 0 (inclusive) and the specified value (exclusive). - * - * @param n the bound on the random number to be returned. Must be - * positive. - * @return the next value - * @throws IllegalArgumentException if n is not positive - */ - public long nextLong(long n) { - if (n <= 0) { - throw new IllegalArgumentException("n must be positive"); - } - - // Divide n by two until small enough for nextInt. On each - // iteration (at most 31 of them but usually much less), - // randomly choose both whether to include high bit in result - // (offset) and whether to continue with the lower vs upper - // half (which makes a difference only if odd). - long offset = 0; - while (n >= Integer.MAX_VALUE) { - int bits = next(2); - long half = n >>> 1; - long nextn = ((bits & 2) == 0) ? half : n - half; - if ((bits & 1) == 0) { - offset += n - nextn; - } - n = nextn; - } - return offset + nextInt((int) n); - } - - /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). - * - * @param least the least value returned - * @param bound the upper bound (exclusive) - * @return the next value - * @throws IllegalArgumentException if least greater than or equal - * to bound - */ - public long nextLong(long least, long bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextLong(bound - least) + least; - } - - /** - * Returns a pseudorandom, uniformly distributed {@code double} value - * between 0 (inclusive) and the specified value (exclusive). - * - * @param n the bound on the random number to be returned. Must be - * positive. - * @return the next value - * @throws IllegalArgumentException if n is not positive - */ - public double nextDouble(double n) { - if (n <= 0) { - throw new IllegalArgumentException("n must be positive"); - } - return nextDouble() * n; - } - - /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). - * - * @param least the least value returned - * @param bound the upper bound (exclusive) - * @return the next value - * @throws IllegalArgumentException if least greater than or equal - * to bound - */ - public double nextDouble(double least, double bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextDouble() * (bound - least) + least; - } - - private static final long serialVersionUID = -5851777807851030925L; -} diff --git a/java/src/game/net/util/internal/TypeParameterMatcher.java b/java/src/game/net/util/internal/TypeParameterMatcher.java deleted file mode 100644 index 66ee164..0000000 --- a/java/src/game/net/util/internal/TypeParameterMatcher.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.lang.reflect.Array; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.HashMap; -import java.util.Map; - -public abstract class TypeParameterMatcher { - - private static final TypeParameterMatcher NOOP = new NoOpTypeParameterMatcher(); - private static final Object TEST_OBJECT = new Object(); - - public static TypeParameterMatcher get(final Class parameterType) { - final Map, TypeParameterMatcher> getCache = - InternalThreadLocalMap.get().typeParameterMatcherGetCache(); - - TypeParameterMatcher matcher = getCache.get(parameterType); - if (matcher == null) { - if (parameterType == Object.class) { - matcher = NOOP; - } -// else if (PlatformDependent.hasJavassist()) { -// try { -// matcher = JavassistTypeParameterMatcherGenerator.generate(parameterType); -// matcher.match(TEST_OBJECT); -// } catch (IllegalAccessError e) { -// // Happens if parameterType is not public. -// matcher = null; -// } catch (Exception e) { -// // Will not usually happen, but just in case. -// matcher = null; -// } -// } - - if (matcher == null) { - matcher = new ReflectiveMatcher(parameterType); - } - - getCache.put(parameterType, matcher); - } - - return matcher; - } - - public static TypeParameterMatcher find( - final Object object, final Class parameterizedSuperclass, final String typeParamName) { - - final Map, Map> findCache = - InternalThreadLocalMap.get().typeParameterMatcherFindCache(); - final Class thisClass = object.getClass(); - - Map map = findCache.get(thisClass); - if (map == null) { - map = new HashMap(); - findCache.put(thisClass, map); - } - - TypeParameterMatcher matcher = map.get(typeParamName); - if (matcher == null) { - matcher = get(find0(object, parameterizedSuperclass, typeParamName)); - map.put(typeParamName, matcher); - } - - return matcher; - } - - private static Class find0( - final Object object, Class parameterizedSuperclass, String typeParamName) { - - final Class thisClass = object.getClass(); - Class currentClass = thisClass; - for (;;) { - if (currentClass.getSuperclass() == parameterizedSuperclass) { - int typeParamIndex = -1; - TypeVariable[] typeParams = currentClass.getSuperclass().getTypeParameters(); - for (int i = 0; i < typeParams.length; i ++) { - if (typeParamName.equals(typeParams[i].getName())) { - typeParamIndex = i; - break; - } - } - - if (typeParamIndex < 0) { - throw new IllegalStateException( - "unknown type parameter '" + typeParamName + "': " + parameterizedSuperclass); - } - - Type genericSuperType = currentClass.getGenericSuperclass(); - if (!(genericSuperType instanceof ParameterizedType)) { - return Object.class; - } - - Type[] actualTypeParams = ((ParameterizedType) genericSuperType).getActualTypeArguments(); - - Type actualTypeParam = actualTypeParams[typeParamIndex]; - if (actualTypeParam instanceof ParameterizedType) { - actualTypeParam = ((ParameterizedType) actualTypeParam).getRawType(); - } - if (actualTypeParam instanceof Class) { - return (Class) actualTypeParam; - } - if (actualTypeParam instanceof GenericArrayType) { - Type componentType = ((GenericArrayType) actualTypeParam).getGenericComponentType(); - if (componentType instanceof ParameterizedType) { - componentType = ((ParameterizedType) componentType).getRawType(); - } - if (componentType instanceof Class) { - return Array.newInstance((Class) componentType, 0).getClass(); - } - } - if (actualTypeParam instanceof TypeVariable) { - // Resolved type parameter points to another type parameter. - TypeVariable v = (TypeVariable) actualTypeParam; - currentClass = thisClass; - if (!(v.getGenericDeclaration() instanceof Class)) { - return Object.class; - } - - parameterizedSuperclass = (Class) v.getGenericDeclaration(); - typeParamName = v.getName(); - if (parameterizedSuperclass.isAssignableFrom(thisClass)) { - continue; - } else { - return Object.class; - } - } - - return fail(thisClass, typeParamName); - } - currentClass = currentClass.getSuperclass(); - if (currentClass == null) { - return fail(thisClass, typeParamName); - } - } - } - - private static Class fail(Class type, String typeParamName) { - throw new IllegalStateException( - "cannot determine the type of the type parameter '" + typeParamName + "': " + type); - } - - public abstract boolean match(Object msg); - - private static final class ReflectiveMatcher extends TypeParameterMatcher { - private final Class type; - - ReflectiveMatcher(Class type) { - this.type = type; - } - - @Override - public boolean match(Object msg) { - return type.isInstance(msg); - } - } - - protected TypeParameterMatcher() { } -} diff --git a/java/src/game/net/util/internal/UnpaddedInternalThreadLocalMap.java b/java/src/game/net/util/internal/UnpaddedInternalThreadLocalMap.java deleted file mode 100644 index e60b3db..0000000 --- a/java/src/game/net/util/internal/UnpaddedInternalThreadLocalMap.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package game.net.util.internal; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * The internal data structure that stores the thread-local variables for Netty and all {@link FastThreadLocal}s. - * Note that this class is for internal use only and is subject to change at any time. Use {@link FastThreadLocal} - * unless you know what you are doing. - */ -class UnpaddedInternalThreadLocalMap { - - static ThreadLocal slowThreadLocalMap; - static final AtomicInteger nextIndex = new AtomicInteger(); - - /** Used by {@link FastThreadLocal} */ - Object[] indexedVariables; - - // Core thread-locals - int futureListenerStackDepth; - int localChannelReaderStackDepth; - Map, Boolean> handlerSharableCache; - IntegerHolder counterHashCode; - ThreadLocalRandom random; - Map, TypeParameterMatcher> typeParameterMatcherGetCache; - Map, Map> typeParameterMatcherFindCache; - - // String-related thread-locals - StringBuilder stringBuilder; - Map charsetEncoderCache; - Map charsetDecoderCache; - - UnpaddedInternalThreadLocalMap(Object[] indexedVariables) { - this.indexedVariables = indexedVariables; - } -} diff --git a/java/src/game/net/util/internal/UnsafeAtomicIntegerFieldUpdater.java b/java/src/game/net/util/internal/UnsafeAtomicIntegerFieldUpdater.java deleted file mode 100644 index 472f85d..0000000 --- a/java/src/game/net/util/internal/UnsafeAtomicIntegerFieldUpdater.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import sun.misc.Unsafe; - -final class UnsafeAtomicIntegerFieldUpdater extends AtomicIntegerFieldUpdater { - private final long offset; - private final Unsafe unsafe; - - UnsafeAtomicIntegerFieldUpdater(Unsafe unsafe, Class tClass, String fieldName) throws NoSuchFieldException { - Field field = tClass.getDeclaredField(fieldName); - if (!Modifier.isVolatile(field.getModifiers())) { - throw new IllegalArgumentException("Must be volatile"); - } - this.unsafe = unsafe; - offset = unsafe.objectFieldOffset(field); - } - - @Override - public boolean compareAndSet(T obj, int expect, int update) { - return unsafe.compareAndSwapInt(obj, offset, expect, update); - } - - @Override - public boolean weakCompareAndSet(T obj, int expect, int update) { - return unsafe.compareAndSwapInt(obj, offset, expect, update); - } - - @Override - public void set(T obj, int newValue) { - unsafe.putIntVolatile(obj, offset, newValue); - } - - @Override - public void lazySet(T obj, int newValue) { - unsafe.putOrderedInt(obj, offset, newValue); - } - - @Override - public int get(T obj) { - return unsafe.getIntVolatile(obj, offset); - } -} diff --git a/java/src/game/net/util/internal/UnsafeAtomicLongFieldUpdater.java b/java/src/game/net/util/internal/UnsafeAtomicLongFieldUpdater.java deleted file mode 100644 index 005595e..0000000 --- a/java/src/game/net/util/internal/UnsafeAtomicLongFieldUpdater.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; - -import sun.misc.Unsafe; - -final class UnsafeAtomicLongFieldUpdater extends AtomicLongFieldUpdater { - private final long offset; - private final Unsafe unsafe; - - UnsafeAtomicLongFieldUpdater(Unsafe unsafe, Class tClass, String fieldName) throws NoSuchFieldException { - Field field = tClass.getDeclaredField(fieldName); - if (!Modifier.isVolatile(field.getModifiers())) { - throw new IllegalArgumentException("Must be volatile"); - } - this.unsafe = unsafe; - offset = unsafe.objectFieldOffset(field); - } - - @Override - public boolean compareAndSet(T obj, long expect, long update) { - return unsafe.compareAndSwapLong(obj, offset, expect, update); - } - - @Override - public boolean weakCompareAndSet(T obj, long expect, long update) { - return unsafe.compareAndSwapLong(obj, offset, expect, update); - } - - @Override - public void set(T obj, long newValue) { - unsafe.putLongVolatile(obj, offset, newValue); - } - - @Override - public void lazySet(T obj, long newValue) { - unsafe.putOrderedLong(obj, offset, newValue); - } - - @Override - public long get(T obj) { - return unsafe.getLongVolatile(obj, offset); - } -} diff --git a/java/src/game/net/util/internal/UnsafeAtomicReferenceFieldUpdater.java b/java/src/game/net/util/internal/UnsafeAtomicReferenceFieldUpdater.java deleted file mode 100644 index 040f920..0000000 --- a/java/src/game/net/util/internal/UnsafeAtomicReferenceFieldUpdater.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -import sun.misc.Unsafe; - -final class UnsafeAtomicReferenceFieldUpdater extends AtomicReferenceFieldUpdater { - private final long offset; - private final Unsafe unsafe; - - UnsafeAtomicReferenceFieldUpdater(Unsafe unsafe, Class tClass, String fieldName) throws NoSuchFieldException { - Field field = tClass.getDeclaredField(fieldName); - if (!Modifier.isVolatile(field.getModifiers())) { - throw new IllegalArgumentException("Must be volatile"); - } - this.unsafe = unsafe; - offset = unsafe.objectFieldOffset(field); - } - - @Override - public boolean compareAndSet(U obj, M expect, M update) { - return unsafe.compareAndSwapObject(obj, offset, expect, update); - } - - @Override - public boolean weakCompareAndSet(U obj, M expect, M update) { - return unsafe.compareAndSwapObject(obj, offset, expect, update); - } - - @Override - public void set(U obj, M newValue) { - unsafe.putObjectVolatile(obj, offset, newValue); - } - - @Override - public void lazySet(U obj, M newValue) { - unsafe.putOrderedObject(obj, offset, newValue); - } - - - @Override - public M get(U obj) { - return (M) unsafe.getObjectVolatile(obj, offset); - } -} diff --git a/java/src/game/net/util/internal/logging/AbstractInternalLogger.java b/java/src/game/net/util/internal/logging/AbstractInternalLogger.java deleted file mode 100644 index 79146b4..0000000 --- a/java/src/game/net/util/internal/logging/AbstractInternalLogger.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal.logging; - -import java.io.ObjectStreamException; -import java.io.Serializable; - -import game.net.util.internal.StringUtil; - -/** - * A skeletal implementation of {@link InternalLogger}. This class implements - * all methods that have a {@link InternalLogLevel} parameter by default to call - * specific logger methods such as {@link #info(String)} or {@link #isInfoEnabled()}. - */ -public abstract class AbstractInternalLogger implements InternalLogger, Serializable { - - private static final long serialVersionUID = -6382972526573193470L; - - private final String name; - - /** - * Creates a new instance. - */ - protected AbstractInternalLogger(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - this.name = name; - } - - @Override - public String name() { - return name; - } - - @Override - public boolean isEnabled(InternalLogLevel level) { - switch (level) { - case TRACE: - return isTraceEnabled(); - case DEBUG: - return isDebugEnabled(); - case INFO: - return isInfoEnabled(); - case WARN: - return isWarnEnabled(); - case ERROR: - return isErrorEnabled(); - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String msg, Throwable cause) { - switch (level) { - case TRACE: - trace(msg, cause); - break; - case DEBUG: - debug(msg, cause); - break; - case INFO: - info(msg, cause); - break; - case WARN: - warn(msg, cause); - break; - case ERROR: - error(msg, cause); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String msg) { - switch (level) { - case TRACE: - trace(msg); - break; - case DEBUG: - debug(msg); - break; - case INFO: - info(msg); - break; - case WARN: - warn(msg); - break; - case ERROR: - error(msg); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String format, Object arg) { - switch (level) { - case TRACE: - trace(format, arg); - break; - case DEBUG: - debug(format, arg); - break; - case INFO: - info(format, arg); - break; - case WARN: - warn(format, arg); - break; - case ERROR: - error(format, arg); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String format, Object argA, Object argB) { - switch (level) { - case TRACE: - trace(format, argA, argB); - break; - case DEBUG: - debug(format, argA, argB); - break; - case INFO: - info(format, argA, argB); - break; - case WARN: - warn(format, argA, argB); - break; - case ERROR: - error(format, argA, argB); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String format, Object... arguments) { - switch (level) { - case TRACE: - trace(format, arguments); - break; - case DEBUG: - debug(format, arguments); - break; - case INFO: - info(format, arguments); - break; - case WARN: - warn(format, arguments); - break; - case ERROR: - error(format, arguments); - break; - default: - throw new Error(); - } - } - - protected Object readResolve() throws ObjectStreamException { - return InternalLoggerFactory.getInstance(name()); - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + '(' + name() + ')'; - } -} diff --git a/java/src/game/net/util/internal/logging/FormattingTuple.java b/java/src/game/net/util/internal/logging/FormattingTuple.java deleted file mode 100644 index 3d335c0..0000000 --- a/java/src/game/net/util/internal/logging/FormattingTuple.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package game.net.util.internal.logging; - -/** - * Holds the results of formatting done by {@link MessageFormatter}. - */ -class FormattingTuple { - - static final FormattingTuple NULL = new FormattingTuple(null); - - private final String message; - private final Throwable throwable; - private final Object[] argArray; - - FormattingTuple(String message) { - this(message, null, null); - } - - FormattingTuple(String message, Object[] argArray, Throwable throwable) { - this.message = message; - this.throwable = throwable; - if (throwable == null) { - this.argArray = argArray; - } else { - this.argArray = trimmedCopy(argArray); - } - } - - static Object[] trimmedCopy(Object[] argArray) { - if (argArray == null || argArray.length == 0) { - throw new IllegalStateException("non-sensical empty or null argument array"); - } - final int trimemdLen = argArray.length - 1; - Object[] trimmed = new Object[trimemdLen]; - System.arraycopy(argArray, 0, trimmed, 0, trimemdLen); - return trimmed; - } - - public String getMessage() { - return message; - } - - public Object[] getArgArray() { - return argArray; - } - - public Throwable getThrowable() { - return throwable; - } -} diff --git a/java/src/game/net/util/internal/logging/InternalLogLevel.java b/java/src/game/net/util/internal/logging/InternalLogLevel.java deleted file mode 100644 index af3681e..0000000 --- a/java/src/game/net/util/internal/logging/InternalLogLevel.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal.logging; - -/** - * The log level that {@link InternalLogger} can log at. - */ -public enum InternalLogLevel { - /** - * 'TRACE' log level. - */ - TRACE, - /** - * 'DEBUG' log level. - */ - DEBUG, - /** - * 'INFO' log level. - */ - INFO, - /** - * 'WARN' log level. - */ - WARN, - /** - * 'ERROR' log level. - */ - ERROR -} diff --git a/java/src/game/net/util/internal/logging/InternalLogger.java b/java/src/game/net/util/internal/logging/InternalLogger.java deleted file mode 100644 index 93e2944..0000000 --- a/java/src/game/net/util/internal/logging/InternalLogger.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package game.net.util.internal.logging; - -/** - * Internal-use-only logger used by Netty. DO NOT - * access this class outside of Netty. - */ -public interface InternalLogger { - - /** - * Return the name of this {@link InternalLogger} instance. - * - * @return name of this logger instance - */ - String name(); - - /** - * Is the logger instance enabled for the TRACE level? - * - * @return True if this Logger is enabled for the TRACE level, - * false otherwise. - */ - boolean isTraceEnabled(); - - /** - * Log a message at the TRACE level. - * - * @param msg the message string to be logged - */ - void trace(String msg); - - /** - * Log a message at the TRACE level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the TRACE level.

- * - * @param format the format string - * @param arg the argument - */ - void trace(String format, Object arg); - - /** - * Log a message at the TRACE level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the TRACE level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void trace(String format, Object argA, Object argB); - - /** - * Log a message at the TRACE level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the TRACE level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for TRACE. The variants taking {@link #trace(String, Object) one} and - * {@link #trace(String, Object, Object) two} arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void trace(String format, Object... arguments); - - /** - * Log an exception (throwable) at the TRACE level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void trace(String msg, Throwable t); - - /** - * Is the logger instance enabled for the DEBUG level? - * - * @return True if this Logger is enabled for the DEBUG level, - * false otherwise. - */ - boolean isDebugEnabled(); - - /** - * Log a message at the DEBUG level. - * - * @param msg the message string to be logged - */ - void debug(String msg); - - /** - * Log a message at the DEBUG level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the DEBUG level.

- * - * @param format the format string - * @param arg the argument - */ - void debug(String format, Object arg); - - /** - * Log a message at the DEBUG level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the DEBUG level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void debug(String format, Object argA, Object argB); - - /** - * Log a message at the DEBUG level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the DEBUG level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for DEBUG. The variants taking - * {@link #debug(String, Object) one} and {@link #debug(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void debug(String format, Object... arguments); - - /** - * Log an exception (throwable) at the DEBUG level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void debug(String msg, Throwable t); - - /** - * Is the logger instance enabled for the INFO level? - * - * @return True if this Logger is enabled for the INFO level, - * false otherwise. - */ - boolean isInfoEnabled(); - - /** - * Log a message at the INFO level. - * - * @param msg the message string to be logged - */ - void info(String msg); - - /** - * Log a message at the INFO level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the INFO level.

- * - * @param format the format string - * @param arg the argument - */ - void info(String format, Object arg); - - /** - * Log a message at the INFO level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the INFO level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void info(String format, Object argA, Object argB); - - /** - * Log a message at the INFO level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the INFO level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for INFO. The variants taking - * {@link #info(String, Object) one} and {@link #info(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void info(String format, Object... arguments); - - /** - * Log an exception (throwable) at the INFO level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void info(String msg, Throwable t); - - /** - * Is the logger instance enabled for the WARN level? - * - * @return True if this Logger is enabled for the WARN level, - * false otherwise. - */ - boolean isWarnEnabled(); - - /** - * Log a message at the WARN level. - * - * @param msg the message string to be logged - */ - void warn(String msg); - - /** - * Log a message at the WARN level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the WARN level.

- * - * @param format the format string - * @param arg the argument - */ - void warn(String format, Object arg); - - /** - * Log a message at the WARN level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the WARN level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for WARN. The variants taking - * {@link #warn(String, Object) one} and {@link #warn(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void warn(String format, Object... arguments); - - /** - * Log a message at the WARN level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the WARN level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void warn(String format, Object argA, Object argB); - - /** - * Log an exception (throwable) at the WARN level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void warn(String msg, Throwable t); - - /** - * Is the logger instance enabled for the ERROR level? - * - * @return True if this Logger is enabled for the ERROR level, - * false otherwise. - */ - boolean isErrorEnabled(); - - /** - * Log a message at the ERROR level. - * - * @param msg the message string to be logged - */ - void error(String msg); - - /** - * Log a message at the ERROR level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the ERROR level.

- * - * @param format the format string - * @param arg the argument - */ - void error(String format, Object arg); - - /** - * Log a message at the ERROR level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the ERROR level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void error(String format, Object argA, Object argB); - - /** - * Log a message at the ERROR level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the ERROR level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for ERROR. The variants taking - * {@link #error(String, Object) one} and {@link #error(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void error(String format, Object... arguments); - - /** - * Log an exception (throwable) at the ERROR level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void error(String msg, Throwable t); - - /** - * Is the logger instance enabled for the specified {@code level}? - * - * @return True if this Logger is enabled for the specified {@code level}, - * false otherwise. - */ - boolean isEnabled(InternalLogLevel level); - - /** - * Log a message at the specified {@code level}. - * - * @param msg the message string to be logged - */ - void log(InternalLogLevel level, String msg); - - /** - * Log a message at the specified {@code level} according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the specified {@code level}.

- * - * @param format the format string - * @param arg the argument - */ - void log(InternalLogLevel level, String format, Object arg); - - /** - * Log a message at the specified {@code level} according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the specified {@code level}.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void log(InternalLogLevel level, String format, Object argA, Object argB); - - /** - * Log a message at the specified {@code level} according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the specified {@code level}. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for the specified {@code level}. The variants taking - * {@link #log(InternalLogLevel, String, Object) one} and - * {@link #log(InternalLogLevel, String, Object, Object) two} arguments exist solely - * in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void log(InternalLogLevel level, String format, Object... arguments); - - /** - * Log an exception (throwable) at the specified {@code level} with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void log(InternalLogLevel level, String msg, Throwable t); -} diff --git a/java/src/game/net/util/internal/logging/InternalLoggerFactory.java b/java/src/game/net/util/internal/logging/InternalLoggerFactory.java deleted file mode 100644 index 18d4cf0..0000000 --- a/java/src/game/net/util/internal/logging/InternalLoggerFactory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal.logging; - -/** - * Creates an {@link InternalLogger} or changes the default factory - * implementation. This factory allows you to choose what logging framework - * Netty should use. The default factory is {@link Slf4JLoggerFactory}. If SLF4J - * is not available, {@link Log4JLoggerFactory} is used. If Log4J is not available, - * {@link JdkLoggerFactory} is used. You can change it to your preferred - * logging framework before other Netty classes are loaded: - *
- * {@link InternalLoggerFactory}.setDefaultFactory(new {@link Log4JLoggerFactory}());
- * 
- * Please note that the new default factory is effective only for the classes - * which were loaded after the default factory is changed. Therefore, - * {@link #setDefaultFactory(InternalLoggerFactory)} should be called as early - * as possible and shouldn't be called more than once. - */ -public abstract class InternalLoggerFactory { - private static volatile InternalLoggerFactory defaultFactory = - newDefaultFactory(InternalLoggerFactory.class.getName()); - -// - private static InternalLoggerFactory newDefaultFactory(String name) { - InternalLoggerFactory f; -// try { -// f = new Slf4JLoggerFactory(true); -// f.newInstance(name).debug("Using SLF4J as the default logging framework"); -// } catch (Throwable t1) { -// try { -// f = new Log4JLoggerFactory(); -// f.newInstance(name).debug("Using Log4J as the default logging framework"); -// } catch (Throwable t2) { - f = new JdkLoggerFactory(); - f.newInstance(name).debug("Using java.util.logging as the default logging framework"); -// } -// } - return f; - } - - /** - * Returns the default factory. The initial default factory is - * {@link JdkLoggerFactory}. - */ - public static InternalLoggerFactory getDefaultFactory() { - return defaultFactory; - } - - /** - * Changes the default factory. - */ - public static void setDefaultFactory(InternalLoggerFactory defaultFactory) { - if (defaultFactory == null) { - throw new NullPointerException("defaultFactory"); - } - InternalLoggerFactory.defaultFactory = defaultFactory; - } - - /** - * Creates a new logger instance with the name of the specified class. - */ - public static InternalLogger getInstance(Class clazz) { - return getInstance(clazz.getName()); - } - - /** - * Creates a new logger instance with the specified name. - */ - public static InternalLogger getInstance(String name) { - return getDefaultFactory().newInstance(name); - } - - /** - * Creates a new logger instance with the specified name. - */ - protected abstract InternalLogger newInstance(String name); -} diff --git a/java/src/game/net/util/internal/logging/JdkLogger.java b/java/src/game/net/util/internal/logging/JdkLogger.java deleted file mode 100644 index e0e9894..0000000 --- a/java/src/game/net/util/internal/logging/JdkLogger.java +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package game.net.util.internal.logging; - -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -/** - * java.util.logging - * logger. - */ -class JdkLogger extends AbstractInternalLogger { - - private static final long serialVersionUID = -1767272577989225979L; - - final transient Logger logger; - - JdkLogger(Logger logger) { - super(logger.getName()); - this.logger = logger; - } - - /** - * Is this logger instance enabled for the FINEST level? - * - * @return True if this Logger is enabled for level FINEST, false otherwise. - */ - @Override - public boolean isTraceEnabled() { - return logger.isLoggable(Level.FINEST); - } - - /** - * Log a message object at level FINEST. - * - * @param msg - * - the message object to be logged - */ - @Override - public void trace(String msg) { - if (logger.isLoggable(Level.FINEST)) { - log(SELF, Level.FINEST, msg, null); - } - } - - /** - * Log a message at level FINEST according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for level FINEST. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void trace(String format, Object arg) { - if (logger.isLoggable(Level.FINEST)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINEST according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINEST level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void trace(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.FINEST)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINEST according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINEST level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void trace(String format, Object... argArray) { - if (logger.isLoggable(Level.FINEST)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at level FINEST with an accompanying message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void trace(String msg, Throwable t) { - if (logger.isLoggable(Level.FINEST)) { - log(SELF, Level.FINEST, msg, t); - } - } - - /** - * Is this logger instance enabled for the FINE level? - * - * @return True if this Logger is enabled for level FINE, false otherwise. - */ - @Override - public boolean isDebugEnabled() { - return logger.isLoggable(Level.FINE); - } - - /** - * Log a message object at level FINE. - * - * @param msg - * - the message object to be logged - */ - @Override - public void debug(String msg) { - if (logger.isLoggable(Level.FINE)) { - log(SELF, Level.FINE, msg, null); - } - } - - /** - * Log a message at level FINE according to the specified format and argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for level FINE. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void debug(String format, Object arg) { - if (logger.isLoggable(Level.FINE)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINE level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void debug(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.FINE)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINE level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void debug(String format, Object... argArray) { - if (logger.isLoggable(Level.FINE)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at level FINE with an accompanying message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void debug(String msg, Throwable t) { - if (logger.isLoggable(Level.FINE)) { - log(SELF, Level.FINE, msg, t); - } - } - - /** - * Is this logger instance enabled for the INFO level? - * - * @return True if this Logger is enabled for the INFO level, false otherwise. - */ - @Override - public boolean isInfoEnabled() { - return logger.isLoggable(Level.INFO); - } - - /** - * Log a message object at the INFO level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void info(String msg) { - if (logger.isLoggable(Level.INFO)) { - log(SELF, Level.INFO, msg, null); - } - } - - /** - * Log a message at level INFO according to the specified format and argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void info(String format, Object arg) { - if (logger.isLoggable(Level.INFO)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the INFO level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void info(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.INFO)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level INFO according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void info(String format, Object... argArray) { - if (logger.isLoggable(Level.INFO)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the INFO level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void info(String msg, Throwable t) { - if (logger.isLoggable(Level.INFO)) { - log(SELF, Level.INFO, msg, t); - } - } - - /** - * Is this logger instance enabled for the WARNING level? - * - * @return True if this Logger is enabled for the WARNING level, false - * otherwise. - */ - @Override - public boolean isWarnEnabled() { - return logger.isLoggable(Level.WARNING); - } - - /** - * Log a message object at the WARNING level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void warn(String msg) { - if (logger.isLoggable(Level.WARNING)) { - log(SELF, Level.WARNING, msg, null); - } - } - - /** - * Log a message at the WARNING level according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARNING level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void warn(String format, Object arg) { - if (logger.isLoggable(Level.WARNING)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the WARNING level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARNING level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void warn(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.WARNING)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level WARNING according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARNING level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void warn(String format, Object... argArray) { - if (logger.isLoggable(Level.WARNING)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the WARNING level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void warn(String msg, Throwable t) { - if (logger.isLoggable(Level.WARNING)) { - log(SELF, Level.WARNING, msg, t); - } - } - - /** - * Is this logger instance enabled for level SEVERE? - * - * @return True if this Logger is enabled for level SEVERE, false otherwise. - */ - @Override - public boolean isErrorEnabled() { - return logger.isLoggable(Level.SEVERE); - } - - /** - * Log a message object at the SEVERE level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void error(String msg) { - if (logger.isLoggable(Level.SEVERE)) { - log(SELF, Level.SEVERE, msg, null); - } - } - - /** - * Log a message at the SEVERE level according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the SEVERE level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void error(String format, Object arg) { - if (logger.isLoggable(Level.SEVERE)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the SEVERE level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the SEVERE level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void error(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.SEVERE)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level SEVERE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the SEVERE level. - *

- * - * @param format - * the format string - * @param arguments - * an array of arguments - */ - @Override - public void error(String format, Object... arguments) { - if (logger.isLoggable(Level.SEVERE)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the SEVERE level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void error(String msg, Throwable t) { - if (logger.isLoggable(Level.SEVERE)) { - log(SELF, Level.SEVERE, msg, t); - } - } - - /** - * Log the message at the specified level with the specified throwable if any. - * This method creates a LogRecord and fills in caller date before calling - * this instance's JDK14 logger. - * - * See bug report #13 for more details. - */ - private void log(String callerFQCN, Level level, String msg, Throwable t) { - // millis and thread are filled by the constructor - LogRecord record = new LogRecord(level, msg); - record.setLoggerName(name()); - record.setThrown(t); - fillCallerData(callerFQCN, record); - logger.log(record); - } - - static final String SELF = JdkLogger.class.getName(); - static final String SUPER = AbstractInternalLogger.class.getName(); - - /** - * Fill in caller data if possible. - * - * @param record - * The record to update - */ - private static void fillCallerData(String callerFQCN, LogRecord record) { - StackTraceElement[] steArray = new Throwable().getStackTrace(); - - int selfIndex = -1; - for (int i = 0; i < steArray.length; i++) { - final String className = steArray[i].getClassName(); - if (className.equals(callerFQCN) || className.equals(SUPER)) { - selfIndex = i; - break; - } - } - - int found = -1; - for (int i = selfIndex + 1; i < steArray.length; i++) { - final String className = steArray[i].getClassName(); - if (!(className.equals(callerFQCN) || className.equals(SUPER))) { - found = i; - break; - } - } - - if (found != -1) { - StackTraceElement ste = steArray[found]; - // setting the class name has the side effect of setting - // the needToInferCaller variable to false. - record.setSourceClassName(ste.getClassName()); - record.setSourceMethodName(ste.getMethodName()); - } - } -} diff --git a/java/src/game/net/util/internal/logging/JdkLoggerFactory.java b/java/src/game/net/util/internal/logging/JdkLoggerFactory.java deleted file mode 100644 index c75005d..0000000 --- a/java/src/game/net/util/internal/logging/JdkLoggerFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package game.net.util.internal.logging; - - -import java.util.logging.Logger; - -/** - * Logger factory which creates a - * java.util.logging - * logger. - */ -public class JdkLoggerFactory extends InternalLoggerFactory { - - @Override - public InternalLogger newInstance(String name) { - return new JdkLogger(Logger.getLogger(name)); - } -} diff --git a/java/src/game/net/util/internal/logging/MessageFormatter.java b/java/src/game/net/util/internal/logging/MessageFormatter.java deleted file mode 100644 index 4c555d0..0000000 --- a/java/src/game/net/util/internal/logging/MessageFormatter.java +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package game.net.util.internal.logging; - -import java.util.HashMap; -import java.util.Map; - -// contributors: lizongbo: proposed special treatment of array parameter values -// Joern Huxhorn: pointed out double[] omission, suggested deep array copy - -/** - * Formats messages according to very simple substitution rules. Substitutions - * can be made 1, 2 or more arguments. - *

- *

- * For example, - *

- *

- * MessageFormatter.format("Hi {}.", "there")
- * 
- *

- * will return the string "Hi there.". - *

- * The {} pair is called the formatting anchor. It serves to designate - * the location where arguments need to be substituted within the message - * pattern. - *

- * In case your message contains the '{' or the '}' character, you do not have - * to do anything special unless the '}' character immediately follows '{'. For - * example, - *

- *

- * MessageFormatter.format("Set {1,2,3} is not equal to {}.", "1,2");
- * 
- *

- * will return the string "Set {1,2,3} is not equal to 1,2.". - *

- *

- * If for whatever reason you need to place the string "{}" in the message - * without its formatting anchor meaning, then you need to escape the - * '{' character with '\', that is the backslash character. Only the '{' - * character should be escaped. There is no need to escape the '}' character. - * For example, - *

- *

- * MessageFormatter.format("Set \\{} is not equal to {}.", "1,2");
- * 
- *

- * will return the string "Set {} is not equal to 1,2.". - *

- *

- * The escaping behavior just described can be overridden by escaping the escape - * character '\'. Calling - *

- *

- * MessageFormatter.format("File name is C:\\\\{}.", "file.zip");
- * 
- *

- * will return the string "File name is C:\file.zip". - *

- *

- * The formatting conventions are different than those of {@link MessageFormat} - * which ships with the Java platform. This is justified by the fact that - * SLF4J's implementation is 10 times faster than that of {@link MessageFormat}. - * This local performance difference is both measurable and significant in the - * larger context of the complete logging processing chain. - *

- *

- * See also {@link #format(String, Object)}, - * {@link #format(String, Object, Object)} and - * {@link #arrayFormat(String, Object[])} methods for more details. - */ -final class MessageFormatter { - static final char DELIM_START = '{'; - static final char DELIM_STOP = '}'; - static final String DELIM_STR = "{}"; - private static final char ESCAPE_CHAR = '\\'; - - /** - * Performs single argument substitution for the 'messagePattern' passed as - * parameter. - *

- * For example, - *

- *

-     * MessageFormatter.format("Hi {}.", "there");
-     * 
- *

- * will return the string "Hi there.". - *

- * - * @param messagePattern The message pattern which will be parsed and formatted - * @param arg The argument to be substituted in place of the formatting anchor - * @return The formatted message - */ - static FormattingTuple format(String messagePattern, Object arg) { - return arrayFormat(messagePattern, new Object[]{arg}); - } - - /** - * Performs a two argument substitution for the 'messagePattern' passed as - * parameter. - *

- * For example, - *

- *

-     * MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob");
-     * 
- *

- * will return the string "Hi Alice. My name is Bob.". - * - * @param messagePattern The message pattern which will be parsed and formatted - * @param argA The argument to be substituted in place of the first formatting - * anchor - * @param argB The argument to be substituted in place of the second formatting - * anchor - * @return The formatted message - */ - static FormattingTuple format(final String messagePattern, - Object argA, Object argB) { - return arrayFormat(messagePattern, new Object[]{argA, argB}); - } - - static Throwable getThrowableCandidate(Object[] argArray) { - if (argArray == null || argArray.length == 0) { - return null; - } - - final Object lastEntry = argArray[argArray.length - 1]; - if (lastEntry instanceof Throwable) { - return (Throwable) lastEntry; - } - return null; - } - - /** - * Same principle as the {@link #format(String, Object)} and - * {@link #format(String, Object, Object)} methods except that any number of - * arguments can be passed in an array. - * - * @param messagePattern The message pattern which will be parsed and formatted - * @param argArray An array of arguments to be substituted in place of formatting - * anchors - * @return The formatted message - */ - static FormattingTuple arrayFormat(final String messagePattern, - final Object[] argArray) { - - Throwable throwableCandidate = getThrowableCandidate(argArray); - - if (messagePattern == null) { - return new FormattingTuple(null, argArray, throwableCandidate); - } - - if (argArray == null) { - return new FormattingTuple(messagePattern); - } - - int i = 0; - int j; - StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50); - - int L; - for (L = 0; L < argArray.length; L++) { - - j = messagePattern.indexOf(DELIM_STR, i); - - if (j == -1) { - // no more variables - if (i == 0) { // this is a simple string - return new FormattingTuple(messagePattern, argArray, - throwableCandidate); - } else { // add the tail string which contains no variables and return - // the result. - sbuf.append(messagePattern.substring(i, messagePattern.length())); - return new FormattingTuple(sbuf.toString(), argArray, - throwableCandidate); - } - } else { - if (isEscapedDelimeter(messagePattern, j)) { - if (!isDoubleEscaped(messagePattern, j)) { - L--; // DELIM_START was escaped, thus should not be incremented - sbuf.append(messagePattern.substring(i, j - 1)); - sbuf.append(DELIM_START); - i = j + 1; - } else { - // The escape character preceding the delimiter start is - // itself escaped: "abc x:\\{}" - // we have to consume one backward slash - sbuf.append(messagePattern.substring(i, j - 1)); - deeplyAppendParameter(sbuf, argArray[L], new HashMap()); - i = j + 2; - } - } else { - // normal case - sbuf.append(messagePattern.substring(i, j)); - deeplyAppendParameter(sbuf, argArray[L], new HashMap()); - i = j + 2; - } - } - } - // append the characters following the last {} pair. - sbuf.append(messagePattern.substring(i, messagePattern.length())); - if (L < argArray.length - 1) { - return new FormattingTuple(sbuf.toString(), argArray, throwableCandidate); - } else { - return new FormattingTuple(sbuf.toString(), argArray, null); - } - } - - static boolean isEscapedDelimeter(String messagePattern, - int delimeterStartIndex) { - - if (delimeterStartIndex == 0) { - return false; - } - return messagePattern.charAt(delimeterStartIndex - 1) == ESCAPE_CHAR; - } - - static boolean isDoubleEscaped(String messagePattern, - int delimeterStartIndex) { - return delimeterStartIndex >= 2 && messagePattern.charAt(delimeterStartIndex - 2) == ESCAPE_CHAR; - } - - // special treatment of array values was suggested by 'lizongbo' - private static void deeplyAppendParameter(StringBuffer sbuf, Object o, - Map seenMap) { - if (o == null) { - sbuf.append("null"); - return; - } - if (!o.getClass().isArray()) { - safeObjectAppend(sbuf, o); - } else { - // check for primitive array types because they - // unfortunately cannot be cast to Object[] - if (o instanceof boolean[]) { - booleanArrayAppend(sbuf, (boolean[]) o); - } else if (o instanceof byte[]) { - byteArrayAppend(sbuf, (byte[]) o); - } else if (o instanceof char[]) { - charArrayAppend(sbuf, (char[]) o); - } else if (o instanceof short[]) { - shortArrayAppend(sbuf, (short[]) o); - } else if (o instanceof int[]) { - intArrayAppend(sbuf, (int[]) o); - } else if (o instanceof long[]) { - longArrayAppend(sbuf, (long[]) o); - } else if (o instanceof float[]) { - floatArrayAppend(sbuf, (float[]) o); - } else if (o instanceof double[]) { - doubleArrayAppend(sbuf, (double[]) o); - } else { - objectArrayAppend(sbuf, (Object[]) o, seenMap); - } - } - } - - private static void safeObjectAppend(StringBuffer sbuf, Object o) { - try { - String oAsString = o.toString(); - sbuf.append(oAsString); - } catch (Throwable t) { - System.err - .println("SLF4J: Failed toString() invocation on an object of type [" - + o.getClass().getName() + ']'); - t.printStackTrace(); - sbuf.append("[FAILED toString()]"); - } - } - - private static void objectArrayAppend(StringBuffer sbuf, Object[] a, - Map seenMap) { - sbuf.append('['); - if (!seenMap.containsKey(a)) { - seenMap.put(a, null); - final int len = a.length; - for (int i = 0; i < len; i++) { - deeplyAppendParameter(sbuf, a[i], seenMap); - if (i != len - 1) { - sbuf.append(", "); - } - } - // allow repeats in siblings - seenMap.remove(a); - } else { - sbuf.append("..."); - } - sbuf.append(']'); - } - - private static void booleanArrayAppend(StringBuffer sbuf, boolean[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void byteArrayAppend(StringBuffer sbuf, byte[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void charArrayAppend(StringBuffer sbuf, char[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void shortArrayAppend(StringBuffer sbuf, short[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void intArrayAppend(StringBuffer sbuf, int[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void longArrayAppend(StringBuffer sbuf, long[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void floatArrayAppend(StringBuffer sbuf, float[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void doubleArrayAppend(StringBuffer sbuf, double[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private MessageFormatter() { - } -} diff --git a/java/src/game/network/IThreadListener.java b/java/src/game/network/IThreadListener.java index 75d05eb..8ce2389 100755 --- a/java/src/game/network/IThreadListener.java +++ b/java/src/game/network/IThreadListener.java @@ -1,6 +1,6 @@ package game.network; -import game.future.ListenableFuture; +import com.google.common.util.concurrent.ListenableFuture; public interface IThreadListener { diff --git a/java/src/game/network/NetConnection.java b/java/src/game/network/NetConnection.java index 999a7b4..09c5ef6 100755 --- a/java/src/game/network/NetConnection.java +++ b/java/src/game/network/NetConnection.java @@ -7,31 +7,32 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.regex.Pattern; -import game.future.ThreadFactoryBuilder; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + import game.log.Log; -import game.net.bootstrap.Bootstrap; -import game.net.channel.Channel; -import game.net.channel.ChannelException; -import game.net.channel.ChannelFuture; -import game.net.channel.ChannelFutureListener; -import game.net.channel.ChannelHandler; -import game.net.channel.ChannelHandlerContext; -import game.net.channel.ChannelInitializer; -import game.net.channel.ChannelOption; -import game.net.channel.EventLoopGroup; -import game.net.channel.SimpleChannelInboundHandler; -import game.net.channel.local.LocalChannel; -import game.net.channel.local.LocalEventLoopGroup; -import game.net.channel.local.LocalServerChannel; -import game.net.channel.nio.NioEventLoopGroup; -import game.net.channel.socket.SocketChannel; -import game.net.channel.socket.nio.NioSocketChannel; -import game.net.handler.timeout.ReadTimeoutHandler; -import game.net.handler.timeout.TimeoutException; -import game.net.util.AttributeKey; -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; import game.network.NetHandler.ThreadQuickExitException; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelException; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.local.LocalChannel; +import io.netty.channel.local.LocalEventLoopGroup; +import io.netty.channel.local.LocalServerChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.TimeoutException; +import io.netty.util.AttributeKey; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; public class NetConnection extends SimpleChannelInboundHandler { diff --git a/java/src/game/network/NetHandlerPlayClient.java b/java/src/game/network/NetHandlerPlayClient.java index 0792266..eea156a 100755 --- a/java/src/game/network/NetHandlerPlayClient.java +++ b/java/src/game/network/NetHandlerPlayClient.java @@ -3,11 +3,13 @@ package game.network; import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Maps; + import java.util.Set; import game.Game; import game.audio.PositionedSound; -import game.collect.Maps; import game.dimension.Dimension; import game.entity.DataWatcher; import game.entity.Entity; diff --git a/java/src/game/network/NetHandlerPlayServer.java b/java/src/game/network/NetHandlerPlayServer.java index 5e0d5d3..513dfe7 100755 --- a/java/src/game/network/NetHandlerPlayServer.java +++ b/java/src/game/network/NetHandlerPlayServer.java @@ -6,7 +6,10 @@ import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; import java.util.Set; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; import game.Server; import game.block.Block; @@ -19,7 +22,6 @@ import game.clipboard.ClipboardPlacer; import game.clipboard.Rotation; import game.clipboard.RotationValue; import game.clipboard.Vector; -import game.collect.Lists; import game.color.TextColor; import game.dimension.Dimension; import game.entity.Entity; @@ -31,7 +33,6 @@ import game.entity.npc.EntityHuman; import game.entity.npc.EntityNPC; import game.entity.projectile.EntityArrow; import game.entity.types.EntityLiving; -import game.future.Futures; import game.init.BlockRegistry; import game.init.Config; import game.init.Config.ValueType; @@ -57,8 +58,6 @@ import game.material.Material; import game.nbt.NBTTagCompound; import game.nbt.NBTTagList; import game.nbt.NBTTagString; -import game.net.util.concurrent.Future; -import game.net.util.concurrent.GenericFutureListener; import game.packet.CPacketAction; import game.packet.CPacketBook; import game.packet.CPacketBreak; @@ -123,6 +122,8 @@ import game.world.State; import game.world.Vec3i; import game.world.World; import game.world.WorldServer; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; public class NetHandlerPlayServer extends NetHandler implements ICrafting { @@ -2685,7 +2686,7 @@ public class NetHandlerPlayServer extends NetHandler implements ICrafting case MAGNET: if(this.isAdmin()) { List list = this.entity.worldObj.getEntitiesWithinAABB(Entity.class, new BoundingBox(this.entity.getPosition().subtract(new BlockPos(128, 128, 128)), this.entity.getPosition().add(new BlockPos(128, 128, 128))), new Predicate() { - public boolean test(Entity entity) { + public boolean apply(Entity entity) { return entity.isEntityAlive() && (entity instanceof EntityItem || entity instanceof EntityXp); } }); diff --git a/java/src/game/network/NettyCompressionDecoder.java b/java/src/game/network/NettyCompressionDecoder.java index 8538e68..0d7d95e 100755 --- a/java/src/game/network/NettyCompressionDecoder.java +++ b/java/src/game/network/NettyCompressionDecoder.java @@ -4,11 +4,11 @@ import java.util.List; import java.util.zip.DataFormatException; import java.util.zip.Inflater; -import game.net.buffer.ByteBuf; -import game.net.buffer.Unpooled; -import game.net.channel.ChannelHandlerContext; -import game.net.handler.codec.ByteToMessageDecoder; -import game.net.handler.codec.DecoderException; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.DecoderException; public class NettyCompressionDecoder extends ByteToMessageDecoder { diff --git a/java/src/game/network/NettyCompressionEncoder.java b/java/src/game/network/NettyCompressionEncoder.java index 6bb5353..b19cfd2 100755 --- a/java/src/game/network/NettyCompressionEncoder.java +++ b/java/src/game/network/NettyCompressionEncoder.java @@ -2,9 +2,9 @@ package game.network; import java.util.zip.Deflater; -import game.net.buffer.ByteBuf; -import game.net.channel.ChannelHandlerContext; -import game.net.handler.codec.MessageToByteEncoder; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; public class NettyCompressionEncoder extends MessageToByteEncoder { diff --git a/java/src/game/network/PacketBuffer.java b/java/src/game/network/PacketBuffer.java index 545725e..ccc6b8e 100755 --- a/java/src/game/network/PacketBuffer.java +++ b/java/src/game/network/PacketBuffer.java @@ -8,12 +8,12 @@ import game.item.ItemStack; import game.nbt.NBTLoader; import game.nbt.NBTSizeTracker; import game.nbt.NBTTagCompound; -import game.net.buffer.ByteBuf; -import game.net.buffer.ByteBufInputStream; -import game.net.buffer.ByteBufOutputStream; -import game.net.handler.codec.DecoderException; -import game.net.handler.codec.EncoderException; import game.world.BlockPos; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.handler.codec.DecoderException; +import io.netty.handler.codec.EncoderException; public class PacketBuffer { @@ -302,7 +302,9 @@ public class PacketBuffer } else { - String s = new String(this.readBytes(i).array(), UTF_8); + byte[] abyte = new byte[i]; + this.readBytes(abyte); + String s = new String(abyte, UTF_8); // this.readBytes(i).array() if (s.length() > maxLength) { diff --git a/java/src/game/network/PacketDecoder.java b/java/src/game/network/PacketDecoder.java index c16f91c..f360e53 100755 --- a/java/src/game/network/PacketDecoder.java +++ b/java/src/game/network/PacketDecoder.java @@ -3,9 +3,9 @@ package game.network; import java.io.IOException; import java.util.List; -import game.net.buffer.ByteBuf; -import game.net.channel.ChannelHandlerContext; -import game.net.handler.codec.ByteToMessageDecoder; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; public class PacketDecoder extends ByteToMessageDecoder { diff --git a/java/src/game/network/PacketEncoder.java b/java/src/game/network/PacketEncoder.java index a7051ac..e00af33 100755 --- a/java/src/game/network/PacketEncoder.java +++ b/java/src/game/network/PacketEncoder.java @@ -3,9 +3,9 @@ package game.network; import java.io.IOException; import game.log.Log; -import game.net.buffer.ByteBuf; -import game.net.channel.ChannelHandlerContext; -import game.net.handler.codec.MessageToByteEncoder; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; public class PacketEncoder extends MessageToByteEncoder { diff --git a/java/src/game/network/PacketPrepender.java b/java/src/game/network/PacketPrepender.java index 8bf55f4..9dd9ab7 100755 --- a/java/src/game/network/PacketPrepender.java +++ b/java/src/game/network/PacketPrepender.java @@ -1,8 +1,8 @@ package game.network; -import game.net.buffer.ByteBuf; -import game.net.channel.ChannelHandlerContext; -import game.net.handler.codec.MessageToByteEncoder; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; public class PacketPrepender extends MessageToByteEncoder { diff --git a/java/src/game/network/PacketRegistry.java b/java/src/game/network/PacketRegistry.java index 394e427..471f85c 100755 --- a/java/src/game/network/PacketRegistry.java +++ b/java/src/game/network/PacketRegistry.java @@ -2,9 +2,10 @@ package game.network; import java.util.Map; -import game.collect.BiMap; -import game.collect.HashBiMap; -import game.collect.Maps; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Maps; + import game.packet.CPacketAction; import game.packet.CPacketBook; import game.packet.CPacketBreak; diff --git a/java/src/game/network/PacketSplitter.java b/java/src/game/network/PacketSplitter.java index f1002d5..dec0660 100755 --- a/java/src/game/network/PacketSplitter.java +++ b/java/src/game/network/PacketSplitter.java @@ -2,11 +2,11 @@ package game.network; import java.util.List; -import game.net.buffer.ByteBuf; -import game.net.buffer.Unpooled; -import game.net.channel.ChannelHandlerContext; -import game.net.handler.codec.ByteToMessageDecoder; -import game.net.handler.codec.CorruptedFrameException; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.CorruptedFrameException; public class PacketSplitter extends ByteToMessageDecoder { diff --git a/java/src/game/packet/S20PacketEntityProperties.java b/java/src/game/packet/S20PacketEntityProperties.java index 34c0c84..99110b9 100755 --- a/java/src/game/packet/S20PacketEntityProperties.java +++ b/java/src/game/packet/S20PacketEntityProperties.java @@ -4,7 +4,8 @@ import java.io.IOException; import java.util.Collection; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.attributes.AttributeInstance; import game.entity.attributes.AttributeModifier; import game.network.NetHandlerPlayClient; diff --git a/java/src/game/packet/S27PacketExplosion.java b/java/src/game/packet/S27PacketExplosion.java index df7f021..a9a1f45 100755 --- a/java/src/game/packet/S27PacketExplosion.java +++ b/java/src/game/packet/S27PacketExplosion.java @@ -4,7 +4,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.network.NetHandlerPlayClient; import game.network.Packet; import game.network.PacketBuffer; diff --git a/java/src/game/packet/S38PacketPlayerListItem.java b/java/src/game/packet/S38PacketPlayerListItem.java index af8c361..41108f6 100755 --- a/java/src/game/packet/S38PacketPlayerListItem.java +++ b/java/src/game/packet/S38PacketPlayerListItem.java @@ -5,7 +5,8 @@ import java.util.Collection; import java.util.Map; import java.util.Map.Entry; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.network.NetHandlerPlayClient; import game.network.NetHandlerPlayServer; import game.network.Packet; diff --git a/java/src/game/packet/SPacketChunkData.java b/java/src/game/packet/SPacketChunkData.java index a32d92e..ea5255a 100755 --- a/java/src/game/packet/SPacketChunkData.java +++ b/java/src/game/packet/SPacketChunkData.java @@ -3,7 +3,8 @@ package game.packet; import java.io.IOException; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.network.NetHandlerPlayClient; import game.network.Packet; import game.network.PacketBuffer; diff --git a/java/src/game/pattern/BlockStateHelper.java b/java/src/game/pattern/BlockStateHelper.java index 2e3972e..4ca2a6f 100755 --- a/java/src/game/pattern/BlockStateHelper.java +++ b/java/src/game/pattern/BlockStateHelper.java @@ -2,10 +2,11 @@ package game.pattern; import java.util.Map; import java.util.Map.Entry; -import java.util.function.Predicate; + +import com.google.common.base.Predicate; +import com.google.common.collect.Maps; import game.block.Block; -import game.collect.Maps; import game.properties.IProperty; import game.world.State; @@ -24,7 +25,7 @@ public class BlockStateHelper implements Predicate return new BlockStateHelper(blockIn); } - public boolean test(State p_apply_1_) + public boolean apply(State p_apply_1_) { if (p_apply_1_ != null && p_apply_1_.getBlock().equals(this.block)) { @@ -32,7 +33,7 @@ public class BlockStateHelper implements Predicate { Object object = p_apply_1_.getValue((IProperty)entry.getKey()); - if (!((Predicate)entry.getValue()).test(object)) + if (!((Predicate)entry.getValue()).apply(object)) { return false; } diff --git a/java/src/game/potion/Potion.java b/java/src/game/potion/Potion.java index ad08f9d..7c15d5d 100755 --- a/java/src/game/potion/Potion.java +++ b/java/src/game/potion/Potion.java @@ -2,9 +2,11 @@ package game.potion; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Maps; + import java.util.Set; -import game.collect.Maps; import game.entity.DamageSource; import game.entity.attributes.Attribute; import game.entity.attributes.AttributeInstance; diff --git a/java/src/game/potion/PotionHelper.java b/java/src/game/potion/PotionHelper.java index 55014d7..db280a2 100755 --- a/java/src/game/potion/PotionHelper.java +++ b/java/src/game/potion/PotionHelper.java @@ -4,8 +4,8 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; public class PotionHelper { diff --git a/java/src/game/properties/PropertyBool.java b/java/src/game/properties/PropertyBool.java index 4d3a8a5..ba755a7 100755 --- a/java/src/game/properties/PropertyBool.java +++ b/java/src/game/properties/PropertyBool.java @@ -2,7 +2,7 @@ package game.properties; import java.util.Collection; -import game.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet; public class PropertyBool extends PropertyHelper { diff --git a/java/src/game/properties/PropertyDirection.java b/java/src/game/properties/PropertyDirection.java index fbcb34a..9ed11d0 100755 --- a/java/src/game/properties/PropertyDirection.java +++ b/java/src/game/properties/PropertyDirection.java @@ -1,11 +1,12 @@ package game.properties; import java.util.Collection; -import java.util.function.Predicate; -import game.collect.Filter; -import game.collect.Lists; -import game.util.Predicates; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; + import game.world.Facing; public class PropertyDirection extends PropertyEnum @@ -28,7 +29,7 @@ public class PropertyDirection extends PropertyEnum */ public static PropertyDirection create(String name, Predicate filter) { - return create(name, Filter.filter(Lists.newArrayList(Facing.values()), filter)); + return create(name, Collections2.filter(Lists.newArrayList(Facing.values()), filter)); } /** diff --git a/java/src/game/properties/PropertyEnum.java b/java/src/game/properties/PropertyEnum.java index 41dc454..4b61357 100755 --- a/java/src/game/properties/PropertyEnum.java +++ b/java/src/game/properties/PropertyEnum.java @@ -2,13 +2,13 @@ package game.properties; import java.util.Collection; import java.util.Map; -import java.util.function.Predicate; -import game.collect.Filter; -import game.collect.ImmutableSet; -import game.collect.Lists; -import game.collect.Maps; -import game.util.Predicates; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; public class PropertyEnum & IStringSerializable> extends PropertyHelper { @@ -53,7 +53,7 @@ public class PropertyEnum & IStringSerializable> extends Prope public static & IStringSerializable> PropertyEnum create(String name, Class clazz, Predicate filter) { - return create(name, clazz, Filter.filter(Lists.newArrayList(clazz.getEnumConstants()), filter)); + return create(name, clazz, Collections2.filter(Lists.newArrayList(clazz.getEnumConstants()), filter)); } public static & IStringSerializable> PropertyEnum create(String name, Class clazz, T... values) diff --git a/java/src/game/properties/PropertyInteger.java b/java/src/game/properties/PropertyInteger.java index d3ff44f..8d2fc49 100755 --- a/java/src/game/properties/PropertyInteger.java +++ b/java/src/game/properties/PropertyInteger.java @@ -3,8 +3,8 @@ package game.properties; import java.util.Collection; import java.util.Set; -import game.collect.ImmutableSet; -import game.collect.Sets; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; public class PropertyInteger extends PropertyHelper { diff --git a/java/src/game/renderer/BlockRenderer.java b/java/src/game/renderer/BlockRenderer.java index 1d54552..30ea0e0 100755 --- a/java/src/game/renderer/BlockRenderer.java +++ b/java/src/game/renderer/BlockRenderer.java @@ -4,10 +4,11 @@ import java.util.BitSet; import java.util.List; import java.util.Map; +import com.google.common.collect.Maps; + import game.Game; import game.block.Block; import game.block.BlockLiquid; -import game.collect.Maps; import game.init.BlockRegistry; import game.init.FluidRegistry; import game.item.ItemStack; diff --git a/java/src/game/renderer/EntityRenderer.java b/java/src/game/renderer/EntityRenderer.java index 5e3dad1..1521ee4 100755 --- a/java/src/game/renderer/EntityRenderer.java +++ b/java/src/game/renderer/EntityRenderer.java @@ -4,7 +4,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.Game; import game.biome.Biome; @@ -218,7 +218,7 @@ public class EntityRenderer { float exp = 1.0F; List list = this.gm.theWorld.getEntitiesInAABBexcluding(entity, entity.getEntityBoundingBox().addCoord(look.xCoord * max, look.yCoord * max, look.zCoord * max).expand((double)exp, (double)exp, (double)exp), new Predicate() { - public boolean test(Entity p_apply_1_) + public boolean apply(Entity p_apply_1_) { return p_apply_1_.canBeCollidedWith(); } diff --git a/java/src/game/renderer/ItemModelMesher.java b/java/src/game/renderer/ItemModelMesher.java index 684e222..07d3e12 100755 --- a/java/src/game/renderer/ItemModelMesher.java +++ b/java/src/game/renderer/ItemModelMesher.java @@ -3,8 +3,9 @@ package game.renderer; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.init.ItemRegistry; import game.item.Item; import game.item.ItemStack; diff --git a/java/src/game/renderer/RenderGlobal.java b/java/src/game/renderer/RenderGlobal.java index 7b290df..f779b77 100755 --- a/java/src/game/renderer/RenderGlobal.java +++ b/java/src/game/renderer/RenderGlobal.java @@ -11,15 +11,16 @@ import java.util.Map; import java.util.Queue; import java.util.Set; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import game.Game; import game.audio.Sound; import game.block.Block; import game.block.BlockChest; import game.block.BlockSign; import game.block.BlockSkull; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; import game.entity.Entity; import game.entity.npc.EntityNPC; import game.entity.projectile.EntityBox; diff --git a/java/src/game/renderer/VertexFormat.java b/java/src/game/renderer/VertexFormat.java index eca8abd..b4f2253 100755 --- a/java/src/game/renderer/VertexFormat.java +++ b/java/src/game/renderer/VertexFormat.java @@ -2,7 +2,8 @@ package game.renderer; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.log.Log; public class VertexFormat diff --git a/java/src/game/renderer/blockmodel/ModelBlock.java b/java/src/game/renderer/blockmodel/ModelBlock.java index d526148..57e7407 100755 --- a/java/src/game/renderer/blockmodel/ModelBlock.java +++ b/java/src/game/renderer/blockmodel/ModelBlock.java @@ -2,8 +2,9 @@ package game.renderer.blockmodel; import java.util.List; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.model.ModelBakery; import game.model.ModelRotation; import game.renderer.Vector3f; diff --git a/java/src/game/renderer/blockmodel/ModelGenerator.java b/java/src/game/renderer/blockmodel/ModelGenerator.java index 6786039..7334f14 100755 --- a/java/src/game/renderer/blockmodel/ModelGenerator.java +++ b/java/src/game/renderer/blockmodel/ModelGenerator.java @@ -4,8 +4,9 @@ import java.io.FileNotFoundException; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.log.Log; import game.renderer.Vector3f; import game.renderer.model.ModelBox; diff --git a/java/src/game/renderer/blockmodel/MultiStateMap.java b/java/src/game/renderer/blockmodel/MultiStateMap.java index 7e0f6dc..b38d13f 100755 --- a/java/src/game/renderer/blockmodel/MultiStateMap.java +++ b/java/src/game/renderer/blockmodel/MultiStateMap.java @@ -4,8 +4,9 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.init.BlockRegistry; import game.properties.IProperty; import game.world.State; diff --git a/java/src/game/renderer/blockmodel/StateMap.java b/java/src/game/renderer/blockmodel/StateMap.java index bd5695c..8e6aaf4 100755 --- a/java/src/game/renderer/blockmodel/StateMap.java +++ b/java/src/game/renderer/blockmodel/StateMap.java @@ -3,8 +3,9 @@ package game.renderer.blockmodel; import java.util.Map; import java.util.Map.Entry; +import com.google.common.collect.Maps; + import game.block.Block; -import game.collect.Maps; import game.properties.IProperty; import game.world.State; diff --git a/java/src/game/renderer/chunk/ChunkCompileTaskGenerator.java b/java/src/game/renderer/chunk/ChunkCompileTaskGenerator.java index 8b2182a..e4844ad 100755 --- a/java/src/game/renderer/chunk/ChunkCompileTaskGenerator.java +++ b/java/src/game/renderer/chunk/ChunkCompileTaskGenerator.java @@ -3,7 +3,8 @@ package game.renderer.chunk; import java.util.List; import java.util.concurrent.locks.ReentrantLock; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.renderer.RegionRenderCacheBuilder; public class ChunkCompileTaskGenerator diff --git a/java/src/game/renderer/chunk/ChunkRenderDispatcher.java b/java/src/game/renderer/chunk/ChunkRenderDispatcher.java index b89ad02..1d34493 100755 --- a/java/src/game/renderer/chunk/ChunkRenderDispatcher.java +++ b/java/src/game/renderer/chunk/ChunkRenderDispatcher.java @@ -7,12 +7,13 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ThreadFactory; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + import game.Game; -import game.collect.Lists; -import game.future.Futures; -import game.future.ListenableFuture; -import game.future.ListenableFutureTask; -import game.future.ThreadFactoryBuilder; import game.renderer.BlockLayer; import game.renderer.RegionRenderCacheBuilder; import game.renderer.RenderBuffer; diff --git a/java/src/game/renderer/chunk/ChunkRenderWorker.java b/java/src/game/renderer/chunk/ChunkRenderWorker.java index de4fb1c..64a644e 100755 --- a/java/src/game/renderer/chunk/ChunkRenderWorker.java +++ b/java/src/game/renderer/chunk/ChunkRenderWorker.java @@ -4,12 +4,14 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CancellationException; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; + import game.Game; -import game.collect.Lists; import game.entity.Entity; -import game.future.FutureCallback; -import game.future.Futures; -import game.future.ListenableFuture; import game.log.Log; import game.renderer.BlockLayer; import game.renderer.RegionRenderCacheBuilder; @@ -185,7 +187,7 @@ public class ChunkRenderWorker implements Runnable Log.JNI.error(p_onFailure_1_, "Fehler beim Rendern des Chunks"); } } - }); + }, MoreExecutors.directExecutor()); } } diff --git a/java/src/game/renderer/chunk/CompiledChunk.java b/java/src/game/renderer/chunk/CompiledChunk.java index 02af409..c271c9c 100755 --- a/java/src/game/renderer/chunk/CompiledChunk.java +++ b/java/src/game/renderer/chunk/CompiledChunk.java @@ -2,7 +2,8 @@ package game.renderer.chunk; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.renderer.BlockLayer; import game.renderer.RenderBuffer; import game.tileentity.TileEntity; diff --git a/java/src/game/renderer/chunk/RenderChunk.java b/java/src/game/renderer/chunk/RenderChunk.java index 26fd30d..a64e190 100755 --- a/java/src/game/renderer/chunk/RenderChunk.java +++ b/java/src/game/renderer/chunk/RenderChunk.java @@ -8,10 +8,11 @@ import java.util.HashSet; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import game.Game; import game.block.Block; -import game.collect.Maps; -import game.collect.Sets; import game.renderer.BlockLayer; import game.renderer.BlockRenderer; import game.renderer.DefaultVertexFormats; diff --git a/java/src/game/renderer/entity/RenderHorse.java b/java/src/game/renderer/entity/RenderHorse.java index 59fb6f9..31d8843 100755 --- a/java/src/game/renderer/entity/RenderHorse.java +++ b/java/src/game/renderer/entity/RenderHorse.java @@ -2,8 +2,9 @@ package game.renderer.entity; import java.util.Set; +import com.google.common.collect.Sets; + import game.Game; -import game.collect.Sets; import game.entity.animal.EntityHorse; import game.renderer.model.ModelHorse; import game.renderer.texture.LayeredTexture; diff --git a/java/src/game/renderer/entity/RenderManager.java b/java/src/game/renderer/entity/RenderManager.java index 597ccbb..a275725 100755 --- a/java/src/game/renderer/entity/RenderManager.java +++ b/java/src/game/renderer/entity/RenderManager.java @@ -2,8 +2,9 @@ package game.renderer.entity; import java.util.Map; +import com.google.common.collect.Maps; + import game.Game; -import game.collect.Maps; import game.entity.Entity; import game.entity.types.EntityLiving; import game.init.EntityRegistry; diff --git a/java/src/game/renderer/entity/RendererLivingEntity.java b/java/src/game/renderer/entity/RendererLivingEntity.java index e1882e9..43a553f 100755 --- a/java/src/game/renderer/entity/RendererLivingEntity.java +++ b/java/src/game/renderer/entity/RendererLivingEntity.java @@ -5,7 +5,8 @@ import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.color.TextColor; import game.entity.Entity; import game.entity.item.EntityCrystal; diff --git a/java/src/game/renderer/layers/LayerExtra.java b/java/src/game/renderer/layers/LayerExtra.java index 7cb293b..678de7f 100755 --- a/java/src/game/renderer/layers/LayerExtra.java +++ b/java/src/game/renderer/layers/LayerExtra.java @@ -2,8 +2,9 @@ package game.renderer.layers; import java.util.List; +import com.google.common.collect.Lists; + import game.Game; -import game.collect.Lists; import game.entity.npc.EntityNPC; import game.init.SpeciesRegistry.ModelType; import game.renderer.GlState; diff --git a/java/src/game/renderer/model/ModelBase.java b/java/src/game/renderer/model/ModelBase.java index cab2677..69dbe4d 100755 --- a/java/src/game/renderer/model/ModelBase.java +++ b/java/src/game/renderer/model/ModelBase.java @@ -3,8 +3,9 @@ package game.renderer.model; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.entity.Entity; import game.entity.types.EntityLiving; import game.rng.Random; diff --git a/java/src/game/renderer/model/ModelRenderer.java b/java/src/game/renderer/model/ModelRenderer.java index 446e942..8d036b5 100755 --- a/java/src/game/renderer/model/ModelRenderer.java +++ b/java/src/game/renderer/model/ModelRenderer.java @@ -2,7 +2,8 @@ package game.renderer.model; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.renderer.RenderBuffer; import game.renderer.Tessellator; import game.window.WCF; diff --git a/java/src/game/renderer/particle/EffectRenderer.java b/java/src/game/renderer/particle/EffectRenderer.java index a72eb1c..26240b1 100755 --- a/java/src/game/renderer/particle/EffectRenderer.java +++ b/java/src/game/renderer/particle/EffectRenderer.java @@ -3,9 +3,10 @@ package game.renderer.particle; import java.util.List; import java.util.Map; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.Block; -import game.collect.Lists; -import game.collect.Maps; import game.entity.Entity; import game.material.Material; import game.renderer.ActiveRenderInfo; diff --git a/java/src/game/renderer/particle/ParticleType.java b/java/src/game/renderer/particle/ParticleType.java index 4e3911e..f1c69a6 100755 --- a/java/src/game/renderer/particle/ParticleType.java +++ b/java/src/game/renderer/particle/ParticleType.java @@ -3,8 +3,8 @@ package game.renderer.particle; import java.util.List; import java.util.Map; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; public enum ParticleType { diff --git a/java/src/game/renderer/texture/EntityTexManager.java b/java/src/game/renderer/texture/EntityTexManager.java index 804fc43..742f0e5 100755 --- a/java/src/game/renderer/texture/EntityTexManager.java +++ b/java/src/game/renderer/texture/EntityTexManager.java @@ -8,12 +8,14 @@ import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import java.util.Set; import game.Game; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; import game.entity.npc.EntityNPC; import game.init.SpeciesRegistry; import game.init.SpeciesRegistry.ModelType; diff --git a/java/src/game/renderer/texture/LayeredTexture.java b/java/src/game/renderer/texture/LayeredTexture.java index be01ddd..9fcf643 100755 --- a/java/src/game/renderer/texture/LayeredTexture.java +++ b/java/src/game/renderer/texture/LayeredTexture.java @@ -6,7 +6,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.log.Log; import game.util.FileUtils; diff --git a/java/src/game/renderer/texture/Stitcher.java b/java/src/game/renderer/texture/Stitcher.java index e2b827d..bf65b25 100755 --- a/java/src/game/renderer/texture/Stitcher.java +++ b/java/src/game/renderer/texture/Stitcher.java @@ -5,8 +5,8 @@ import java.util.Arrays; import java.util.List; import java.util.Set; -import game.collect.Lists; -import game.collect.Sets; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; public class Stitcher { diff --git a/java/src/game/renderer/texture/TextureAtlasSprite.java b/java/src/game/renderer/texture/TextureAtlasSprite.java index d7ac2d9..5016b1d 100755 --- a/java/src/game/renderer/texture/TextureAtlasSprite.java +++ b/java/src/game/renderer/texture/TextureAtlasSprite.java @@ -4,7 +4,7 @@ import java.awt.image.BufferedImage; import java.io.IOException; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; public class TextureAtlasSprite { diff --git a/java/src/game/renderer/texture/TextureManager.java b/java/src/game/renderer/texture/TextureManager.java index ba23e7a..88a167e 100755 --- a/java/src/game/renderer/texture/TextureManager.java +++ b/java/src/game/renderer/texture/TextureManager.java @@ -5,7 +5,8 @@ import java.io.IOException; import java.util.Map; import java.util.Map.Entry; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.log.Log; import game.renderer.GlState; diff --git a/java/src/game/renderer/texture/TextureMap.java b/java/src/game/renderer/texture/TextureMap.java index 2957aed..01e3d1a 100755 --- a/java/src/game/renderer/texture/TextureMap.java +++ b/java/src/game/renderer/texture/TextureMap.java @@ -7,9 +7,10 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.Block; -import game.collect.Lists; -import game.collect.Maps; import game.init.BlockRegistry; import game.init.FluidRegistry; import game.log.Log; diff --git a/java/src/game/renderer/tileentity/TileEntityBannerRenderer.java b/java/src/game/renderer/tileentity/TileEntityBannerRenderer.java index ee6e62d..492d56b 100755 --- a/java/src/game/renderer/tileentity/TileEntityBannerRenderer.java +++ b/java/src/game/renderer/tileentity/TileEntityBannerRenderer.java @@ -4,9 +4,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.Game; -import game.collect.Lists; -import game.collect.Maps; import game.color.DyeColor; import game.init.Blocks; import game.renderer.GlState; diff --git a/java/src/game/renderer/tileentity/TileEntityRendererDispatcher.java b/java/src/game/renderer/tileentity/TileEntityRendererDispatcher.java index dca65f4..348a566 100755 --- a/java/src/game/renderer/tileentity/TileEntityRendererDispatcher.java +++ b/java/src/game/renderer/tileentity/TileEntityRendererDispatcher.java @@ -2,7 +2,8 @@ package game.renderer.tileentity; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.entity.Entity; import game.renderer.GlState; import game.renderer.texture.TextureManager; diff --git a/java/src/game/rng/WeightedList.java b/java/src/game/rng/WeightedList.java index 575c324..5b1a01a 100755 --- a/java/src/game/rng/WeightedList.java +++ b/java/src/game/rng/WeightedList.java @@ -3,7 +3,7 @@ package game.rng; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import java.util.function.UnaryOperator; public class WeightedList extends ArrayList { diff --git a/java/src/game/tileentity/TileEntityBanner.java b/java/src/game/tileentity/TileEntityBanner.java index 24b8210..f3ebbfc 100755 --- a/java/src/game/tileentity/TileEntityBanner.java +++ b/java/src/game/tileentity/TileEntityBanner.java @@ -2,8 +2,9 @@ package game.tileentity; import java.util.List; +import com.google.common.collect.Lists; + import game.block.BlockFlower; -import game.collect.Lists; import game.color.DyeColor; import game.init.Blocks; import game.init.Items; diff --git a/java/src/game/tileentity/TileEntityHopper.java b/java/src/game/tileentity/TileEntityHopper.java index 80d75de..56d9767 100755 --- a/java/src/game/tileentity/TileEntityHopper.java +++ b/java/src/game/tileentity/TileEntityHopper.java @@ -1,7 +1,7 @@ package game.tileentity; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.block.Block; import game.block.BlockChest; @@ -633,7 +633,7 @@ public class TileEntityHopper extends TileEntityLockable implements IHopper, ITi public static List func_181556_a(World p_181556_0_, double p_181556_1_, double p_181556_3_, double p_181556_5_) { return p_181556_0_.getEntitiesWithinAABB(EntityItem.class, new BoundingBox(p_181556_1_ - 0.5D, p_181556_3_ - 0.5D, p_181556_5_ - 0.5D, p_181556_1_ + 0.5D, p_181556_3_ + 0.5D, p_181556_5_ + 0.5D), new Predicate() { - public boolean test(EntityItem entity) { + public boolean apply(EntityItem entity) { return entity.isEntityAlive(); } }); @@ -669,7 +669,7 @@ public class TileEntityHopper extends TileEntityLockable implements IHopper, ITi if (iinventory == null) { List list = worldIn.getEntitiesInAABBexcluding((Entity)null, new BoundingBox(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), new Predicate() { - public boolean test(Entity entity) { + public boolean apply(Entity entity) { return entity instanceof IInventory && entity.isEntityAlive(); } }); diff --git a/java/src/game/tileentity/TileEntityPiston.java b/java/src/game/tileentity/TileEntityPiston.java index 98fdb26..0aa6890 100755 --- a/java/src/game/tileentity/TileEntityPiston.java +++ b/java/src/game/tileentity/TileEntityPiston.java @@ -2,7 +2,8 @@ package game.tileentity; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.entity.Entity; import game.init.BlockRegistry; import game.init.Blocks; diff --git a/java/src/game/util/FileUtils.java b/java/src/game/util/FileUtils.java index 547a9b3..b2b86d2 100644 --- a/java/src/game/util/FileUtils.java +++ b/java/src/game/util/FileUtils.java @@ -9,7 +9,7 @@ import java.io.IOException; import java.io.InputStream; import game.log.Log; -import game.net.util.CharsetUtil; +import io.netty.util.CharsetUtil; public class FileUtils { public static String read(InputStream input) throws IOException { diff --git a/java/src/game/util/Predicates.java b/java/src/game/util/Predicates.java deleted file mode 100644 index 27ad39e..0000000 --- a/java/src/game/util/Predicates.java +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package game.util; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Static utility methods pertaining to {@code Predicate} instances. - * - *

All methods returns serializable predicates as long as they're given - * serializable parameters. - * - *

See the Guava User Guide article on the - * use of {@code Predicate}. - * - * @author Kevin Bourrillion - * @since 2.0 (imported from Google Collections Library) - */ - -public final class Predicates { - private Predicates() {} - - // TODO(kevinb): considering having these implement a VisitablePredicate - // interface which specifies an accept(PredicateVisitor) method. - - /** - * Returns a predicate that always evaluates to {@code true}. - */ - - public static Predicate alwaysTrue() { - return ObjectPredicate.ALWAYS_TRUE.withNarrowedType(); - } - - /** - * Returns a predicate that always evaluates to {@code false}. - */ -// -// public static Predicate alwaysFalse() { -// return ObjectPredicate.ALWAYS_FALSE.withNarrowedType(); -// } - - /** - * Returns a predicate that evaluates to {@code true} if the object reference - * being tested is null. - */ - - public static Predicate isNull() { - return ObjectPredicate.IS_NULL.withNarrowedType(); - } - - /** - * Returns a predicate that evaluates to {@code true} if the object reference - * being tested is not null. - */ - - public static Predicate notNull() { - return ObjectPredicate.NOT_NULL.withNarrowedType(); - } - - /** - * Returns a predicate that evaluates to {@code true} if the given predicate - * evaluates to {@code false}. - */ - public static Predicate not(Predicate predicate) { - return new NotPredicate(predicate); - } - - /** - * Returns a predicate that evaluates to {@code true} if each of its - * components evaluates to {@code true}. The components are evaluated in - * order, and evaluation will be "short-circuited" as soon as a false - * predicate is found. It defensively copies the iterable passed in, so future - * changes to it won't alter the behavior of this predicate. If {@code - * components} is empty, the returned predicate will always evaluate to {@code - * true}. - */ -// public static Predicate and( -// Iterable> components) { -// return new AndPredicate(defensiveCopy(components)); -// } - - /** - * Returns a predicate that evaluates to {@code true} if each of its - * components evaluates to {@code true}. The components are evaluated in - * order, and evaluation will be "short-circuited" as soon as a false - * predicate is found. It defensively copies the array passed in, so future - * changes to it won't alter the behavior of this predicate. If {@code - * components} is empty, the returned predicate will always evaluate to {@code - * true}. - */ - public static Predicate and(Predicate... components) { - return new AndPredicate(defensiveCopy(components)); - } - - /** - * Returns a predicate that evaluates to {@code true} if both of its - * components evaluate to {@code true}. The components are evaluated in - * order, and evaluation will be "short-circuited" as soon as a false - * predicate is found. - */ - public static Predicate and(Predicate first, - Predicate second) { - return new AndPredicate(Predicates.asList( - first, second)); - } - - /** - * Returns a predicate that evaluates to {@code true} if any one of its - * components evaluates to {@code true}. The components are evaluated in - * order, and evaluation will be "short-circuited" as soon as a - * true predicate is found. It defensively copies the iterable passed in, so - * future changes to it won't alter the behavior of this predicate. If {@code - * components} is empty, the returned predicate will always evaluate to {@code - * false}. - */ -// public static Predicate or( -// Iterable> components) { -// return new OrPredicate(defensiveCopy(components)); -// } - - /** - * Returns a predicate that evaluates to {@code true} if any one of its - * components evaluates to {@code true}. The components are evaluated in - * order, and evaluation will be "short-circuited" as soon as a - * true predicate is found. It defensively copies the array passed in, so - * future changes to it won't alter the behavior of this predicate. If {@code - * components} is empty, the returned predicate will always evaluate to {@code - * false}. - */ -// public static Predicate or(Predicate... components) { -// return new OrPredicate(defensiveCopy(components)); -// } - - /** - * Returns a predicate that evaluates to {@code true} if either of its - * components evaluates to {@code true}. The components are evaluated in - * order, and evaluation will be "short-circuited" as soon as a - * true predicate is found. - */ -// public static Predicate or( -// Predicate first, Predicate second) { -// return new OrPredicate(Predicates.asList( -// checkNotNull(first), checkNotNull(second))); -// } - - /** - * Returns a predicate that evaluates to {@code true} if the object being - * tested {@code equals()} the given target or both are null. - */ - public static Predicate equalTo(T target) { - return (target == null) - ? Predicates.isNull() - : new IsEqualToPredicate(target); - } - - /** - * Returns a predicate that evaluates to {@code true} if the object being - * tested is an instance of the given class. If the object being tested - * is {@code null} this predicate evaluates to {@code false}. - * - *

If you want to filter an {@code Iterable} to narrow its type, consider - * using {@link com.google.common.collect.Iterables#filter(Iterable, Class)} - * in preference. - * - *

Warning: contrary to the typical assumptions about predicates (as - * documented at {@link Predicate#apply}), the returned predicate may not be - * consistent with equals. For example, {@code - * instanceOf(ArrayList.class)} will yield different results for the two equal - * instances {@code Lists.newArrayList(1)} and {@code Arrays.asList(1)}. - */ - - public static Predicate instanceOf(Class clazz) { - return new InstanceOfPredicate(clazz); - } - - /** - * Returns a predicate that evaluates to {@code true} if the class being - * tested is assignable from the given class. The returned predicate - * does not allow null inputs. - * - * @since 10.0 - */ -// -// @Beta -// public static Predicate> assignableFrom(Class clazz) { -// return new AssignableFromPredicate(clazz); -// } - - /** - * Returns a predicate that evaluates to {@code true} if the object reference - * being tested is a member of the given collection. It does not defensively - * copy the collection passed in, so future changes to it will alter the - * behavior of the predicate. - * - *

This method can technically accept any {@code Collection}, but using - * a typed collection helps prevent bugs. This approach doesn't block any - * potential users since it is always possible to use {@code - * Predicates.in()}. - * - * @param target the collection that may contain the function input - */ - public static Predicate in(Collection target) { - return new InPredicate(target); - } - - /** - * Returns the composition of a function and a predicate. For every {@code x}, - * the generated predicate returns {@code predicate(function(x))}. - * - * @return the composition of the provided function and predicate - */ - public static Predicate compose( - Predicate predicate, Function function) { - return new CompositionPredicate(predicate, function); - } - - /** - * Returns a predicate that evaluates to {@code true} if the - * {@code CharSequence} being tested contains any match for the given - * regular expression pattern. The test used is equivalent to - * {@code Pattern.compile(pattern).matcher(arg).find()} - * - * @throws java.util.regex.PatternSyntaxException if the pattern is invalid - * @since 3.0 - */ -// -// public static Predicate containsPattern(String pattern) { -// return new ContainsPatternFromStringPredicate(pattern); -// } - - /** - * Returns a predicate that evaluates to {@code true} if the - * {@code CharSequence} being tested contains any match for the given - * regular expression pattern. The test used is equivalent to - * {@code pattern.matcher(arg).find()} - * - * @since 3.0 - */ - -// public static Predicate contains(Pattern pattern) { -// return new ContainsPatternPredicate(pattern); -// } - - // End public API, begin private implementation classes. - - // Package private for GWT serialization. - enum ObjectPredicate implements Predicate { - /** @see Predicates#alwaysTrue() */ - ALWAYS_TRUE { - @Override public boolean test(Object o) { - return true; - } -// @Override public String toString() { -// return "Predicates.alwaysTrue()"; -// } - }, - /** @see Predicates#alwaysFalse() */ -// ALWAYS_FALSE { -// @Override public boolean test(Object o) { -// return false; -// } -// @Override public String toString() { -// return "Predicates.alwaysFalse()"; -// } -// }, - /** @see Predicates#isNull() */ - IS_NULL { - @Override public boolean test(Object o) { - return o == null; - } -// @Override public String toString() { -// return "Predicates.isNull()"; -// } - }, - /** @see Predicates#notNull() */ - NOT_NULL { - @Override public boolean test(Object o) { - return o != null; - } -// @Override public String toString() { -// return "Predicates.notNull()"; -// } - }; - - // safe contravariant cast - Predicate withNarrowedType() { - return (Predicate) this; - } - } - - /** @see Predicates#not(Predicate) */ - private static class NotPredicate implements Predicate, Serializable { - final Predicate predicate; - - NotPredicate(Predicate predicate) { - this.predicate = predicate; - } - @Override - public boolean test(T t) { - return !predicate.test(t); - } -// @Override public int hashCode() { -// return ~predicate.hashCode(); -// } -// @Override public boolean equals(Object obj) { -// if (obj instanceof NotPredicate) { -// NotPredicate that = (NotPredicate) obj; -// return predicate.equals(that.predicate); -// } -// return false; -// } -// @Override public String toString() { -// return "Predicates.not(" + predicate.toString() + ")"; -// } -// private static final long serialVersionUID = 0; - } - -// private static final Joiner COMMA_JOINER = Joiner.on(','); - - /** @see Predicates#and(Iterable) */ - private static class AndPredicate implements Predicate, Serializable { - private final List> components; - - private AndPredicate(List> components) { - this.components = components; - } - @Override - public boolean test(T t) { - // Avoid using the Iterator to avoid generating garbage (issue 820). - for (int i = 0; i < components.size(); i++) { - if (!components.get(i).test(t)) { - return false; - } - } - return true; - } -// @Override public int hashCode() { -// // add a random number to avoid collisions with OrPredicate -// return components.hashCode() + 0x12472c2c; -// } -// @Override public boolean equals(Object obj) { -// if (obj instanceof AndPredicate) { -// AndPredicate that = (AndPredicate) obj; -// return components.equals(that.components); -// } -// return false; -// } -// @Override public String toString() { -// return "Predicates.and(" + COMMA_JOINER.join(components) + ")"; -// } -// private static final long serialVersionUID = 0; - } - - /** @see Predicates#or(Iterable) */ -// private static class OrPredicate implements Predicate, Serializable { -// private final List> components; -// -// private OrPredicate(List> components) { -// this.components = components; -// } -// @Override -// public boolean test(T t) { -// // Avoid using the Iterator to avoid generating garbage (issue 820). -// for (int i = 0; i < components.size(); i++) { -// if (components.get(i).test(t)) { -// return true; -// } -// } -// return false; -// } -// @Override public int hashCode() { -// // add a random number to avoid collisions with AndPredicate -// return components.hashCode() + 0x053c91cf; -// } -// @Override public boolean equals(Object obj) { -// if (obj instanceof OrPredicate) { -// OrPredicate that = (OrPredicate) obj; -// return components.equals(that.components); -// } -// return false; -// } -// @Override public String toString() { -// return "Predicates.or(" + COMMA_JOINER.join(components) + ")"; -// } -// private static final long serialVersionUID = 0; -// } - - /** @see Predicates#equalTo(Object) */ - private static class IsEqualToPredicate - implements Predicate, Serializable { - private final T target; - - private IsEqualToPredicate(T target) { - this.target = target; - } - @Override - public boolean test(T t) { - return target.equals(t); - } -// @Override public int hashCode() { -// return target.hashCode(); -// } -// @Override public boolean equals(Object obj) { -// if (obj instanceof IsEqualToPredicate) { -// IsEqualToPredicate that = (IsEqualToPredicate) obj; -// return target.equals(that.target); -// } -// return false; -// } -// @Override public String toString() { -// return "Predicates.equalTo(" + target + ")"; -// } -// private static final long serialVersionUID = 0; - } - - /** @see Predicates#instanceOf(Class) */ - - private static class InstanceOfPredicate - implements Predicate, Serializable { - private final Class clazz; - - private InstanceOfPredicate(Class clazz) { - this.clazz = clazz; - } - @Override - public boolean test(Object o) { - return clazz.isInstance(o); - } -// @Override public int hashCode() { -// return clazz.hashCode(); -// } -// @Override public boolean equals(Object obj) { -// if (obj instanceof InstanceOfPredicate) { -// InstanceOfPredicate that = (InstanceOfPredicate) obj; -// return clazz == that.clazz; -// } -// return false; -// } -// @Override public String toString() { -// return "Predicates.instanceOf(" + clazz.getName() + ")"; -// } -// private static final long serialVersionUID = 0; - } - - /** @see Predicates#assignableFrom(Class) */ - -// private static class AssignableFromPredicate -// implements Predicate>, Serializable { -// private final Class clazz; -// -// private AssignableFromPredicate(Class clazz) { -// this.clazz = checkNotNull(clazz); -// } -// @Override -// public boolean test(Class input) { -// return clazz.isAssignableFrom(input); -// } -// @Override public int hashCode() { -// return clazz.hashCode(); -// } -// @Override public boolean equals(Object obj) { -// if (obj instanceof AssignableFromPredicate) { -// AssignableFromPredicate that = (AssignableFromPredicate) obj; -// return clazz == that.clazz; -// } -// return false; -// } -// @Override public String toString() { -// return "Predicates.assignableFrom(" + clazz.getName() + ")"; -// } -// private static final long serialVersionUID = 0; -// } - - /** @see Predicates#in(Collection) */ - private static class InPredicate implements Predicate, Serializable { - private final Collection target; - - private InPredicate(Collection target) { - this.target = target; - } - - @Override - public boolean test(T t) { - try { - return target.contains(t); - } catch (NullPointerException e) { - return false; - } catch (ClassCastException e) { - return false; - } - } - -// @Override public boolean equals(Object obj) { -// if (obj instanceof InPredicate) { -// InPredicate that = (InPredicate) obj; -// return target.equals(that.target); -// } -// return false; -// } -// -// @Override public int hashCode() { -// return target.hashCode(); -// } - -// @Override public String toString() { -// return "Predicates.in(" + target + ")"; -// } -// private static final long serialVersionUID = 0; - } - - /** @see Predicates#compose(Predicate, Function) */ - private static class CompositionPredicate - implements Predicate, Serializable { - final Predicate p; - final Function f; - - private CompositionPredicate(Predicate p, Function f) { - this.p = p; - this.f = f; - } - - @Override - public boolean test(A a) { - return p.test(f.apply(a)); - } - -// @Override public boolean equals(Object obj) { -// if (obj instanceof CompositionPredicate) { -// CompositionPredicate that = (CompositionPredicate) obj; -// return f.equals(that.f) && p.equals(that.p); -// } -// return false; -// } -// -// @Override public int hashCode() { -// return f.hashCode() ^ p.hashCode(); -// } - -// @Override public String toString() { -// return p.toString() + "(" + f.toString() + ")"; -// } -// -// private static final long serialVersionUID = 0; - } - - /** @see Predicates#contains(Pattern) */ - -// private static class ContainsPatternPredicate -// implements Predicate, Serializable { -// final Pattern pattern; -// -// ContainsPatternPredicate(Pattern pattern) { -// this.pattern = checkNotNull(pattern); -// } -// -// @Override -// public boolean test(CharSequence t) { -// return pattern.matcher(t).find(); -// } -// -// @Override public int hashCode() { -// // Pattern uses Object.hashCode, so we have to reach -// // inside to build a hashCode consistent with equals. -// -// return Arrays.hashCode(new Object[] {pattern.pattern(), pattern.flags()}); -// } -// -// @Override public boolean equals(Object obj) { -// if (obj instanceof ContainsPatternPredicate) { -// ContainsPatternPredicate that = (ContainsPatternPredicate) obj; -// -// // Pattern uses Object (identity) equality, so we have to reach -// // inside to compare individual fields. -// return Objects.equal(pattern.pattern(), that.pattern.pattern()) -// && Objects.equal(pattern.flags(), that.pattern.flags()); -// } -// return false; -// } -// -//// @Override public String toString() { -//// String patternString = Objects.toStringHelper(pattern) -//// .add("pattern", pattern.pattern()) -//// .add("pattern.flags", pattern.flags()) -//// .toString(); -//// return "Predicates.contains(" + patternString + ")"; -//// } -// -// private static final long serialVersionUID = 0; -// } -// -// /** @see Predicates#containsPattern(String) */ -// -// private static class ContainsPatternFromStringPredicate -// extends ContainsPatternPredicate { -// -// ContainsPatternFromStringPredicate(String string) { -// super(Pattern.compile(string)); -// } -// -//// @Override public String toString() { -//// return "Predicates.containsPattern(" + pattern.pattern() + ")"; -//// } -// -// private static final long serialVersionUID = 0; -// } - - private static List> asList( - Predicate first, Predicate second) { - // TODO(kevinb): understand why we still get a warning despite @SafeVarargs! - return Arrays.>asList(first, second); - } - - private static List defensiveCopy(T... array) { - return defensiveCopy(Arrays.asList(array)); - } - - static List defensiveCopy(Iterable iterable) { - ArrayList list = new ArrayList(); - for (T element : iterable) { - list.add(element); - } - return list; - } -} diff --git a/java/src/game/village/Village.java b/java/src/game/village/Village.java index 5c80e39..eac4fd1 100755 --- a/java/src/game/village/Village.java +++ b/java/src/game/village/Village.java @@ -3,9 +3,10 @@ package game.village; import java.util.Iterator; import java.util.List; +import com.google.common.collect.Lists; + import game.block.Block; import game.block.BlockDoor; -import game.collect.Lists; import game.material.Material; import game.nbt.NBTTagCompound; import game.nbt.NBTTagList; diff --git a/java/src/game/village/VillageCollection.java b/java/src/game/village/VillageCollection.java index 74b0a9e..e93cb48 100755 --- a/java/src/game/village/VillageCollection.java +++ b/java/src/game/village/VillageCollection.java @@ -3,9 +3,10 @@ package game.village; import java.util.Iterator; import java.util.List; +import com.google.common.collect.Lists; + import game.block.Block; import game.block.BlockDoor; -import game.collect.Lists; import game.material.Material; import game.nbt.NBTTagCompound; import game.nbt.NBTTagList; diff --git a/java/src/game/world/BlockPos.java b/java/src/game/world/BlockPos.java index 9a8abf2..b9d67a0 100755 --- a/java/src/game/world/BlockPos.java +++ b/java/src/game/world/BlockPos.java @@ -2,7 +2,8 @@ package game.world; import java.util.Iterator; -import game.collect.AbstractIterator; +import com.google.common.collect.AbstractIterator; + import game.entity.Entity; public class BlockPos extends Vec3i diff --git a/java/src/game/world/Chunk.java b/java/src/game/world/Chunk.java index 336e6fb..373c319 100755 --- a/java/src/game/world/Chunk.java +++ b/java/src/game/world/Chunk.java @@ -4,12 +4,13 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Maps; import game.biome.Biome; import game.block.Block; import game.block.ITileEntityProvider; -import game.collect.Maps; import game.entity.Entity; import game.init.Blocks; import game.log.Log; @@ -741,7 +742,7 @@ public class Chunk { if(!this.entities[y].isEmpty()) { for(Entity entity : this.entities[y]) { if(entity.getEntityBoundingBox().intersectsWith(bb) && entity != exclude) { - if(pred == null || pred.test(entity)) { + if(pred == null || pred.apply(entity)) { list.add(entity); } @@ -752,7 +753,7 @@ public class Chunk { entity = parts[l]; if(entity != exclude && entity.getEntityBoundingBox().intersectsWith(bb) - && (pred == null || pred.test(entity))) { + && (pred == null || pred.apply(entity))) { list.add(entity); } } @@ -771,7 +772,7 @@ public class Chunk { for(int y = sy; y <= ey; ++y) { for(T entity : this.entities[y].getByClass(clazz)) { - if(entity.getEntityBoundingBox().intersectsWith(bb) && (pred == null || pred.test(entity))) { + if(entity.getEntityBoundingBox().intersectsWith(bb) && (pred == null || pred.apply(entity))) { list.add(entity); } } diff --git a/java/src/game/world/ClassInheritanceMultiMap.java b/java/src/game/world/ClassInheritanceMultiMap.java index fe7eecd..93470be 100755 --- a/java/src/game/world/ClassInheritanceMultiMap.java +++ b/java/src/game/world/ClassInheritanceMultiMap.java @@ -8,9 +8,9 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import game.collect.Iterators; -import game.collect.Lists; -import game.collect.Maps; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; public class ClassInheritanceMultiMap extends AbstractSet { @@ -128,7 +128,7 @@ public class ClassInheritanceMultiMap extends AbstractSet if (list == null) { - return Iterators.emptyIterator(); + return Collections.emptyIterator(); } else { @@ -141,7 +141,7 @@ public class ClassInheritanceMultiMap extends AbstractSet public Iterator iterator() { - return this.values.isEmpty() ? Iterators.emptyIterator() : Iterators.unmodifiableIterator(this.values.iterator()); + return this.values.isEmpty() ? Collections.emptyIterator() : Iterators.unmodifiableIterator(this.values.iterator()); } public int size() diff --git a/java/src/game/world/Converter.java b/java/src/game/world/Converter.java index 1df716d..b955d75 100755 --- a/java/src/game/world/Converter.java +++ b/java/src/game/world/Converter.java @@ -13,6 +13,8 @@ import java.util.Map.Entry; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; +import com.google.common.collect.Maps; + import game.biome.Biome; import game.block.Block; import game.block.BlockCactus; @@ -39,7 +41,6 @@ import game.block.BlockTNT; import game.block.BlockTallGrass; import game.block.BlockWall; import game.block.LeavesType; -import game.collect.Maps; import game.color.DyeColor; import game.entity.Entity; import game.entity.animal.EntityBat; diff --git a/java/src/game/world/EmptyChunk.java b/java/src/game/world/EmptyChunk.java index 00392cd..ffd1187 100755 --- a/java/src/game/world/EmptyChunk.java +++ b/java/src/game/world/EmptyChunk.java @@ -1,7 +1,7 @@ package game.world; import java.util.List; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import game.block.Block; import game.entity.Entity; diff --git a/java/src/game/world/Explosion.java b/java/src/game/world/Explosion.java index 20351fd..694a439 100755 --- a/java/src/game/world/Explosion.java +++ b/java/src/game/world/Explosion.java @@ -4,10 +4,11 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import game.block.Block; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; import game.enchantment.EnchantmentProtection; import game.entity.DamageSource; import game.entity.Entity; diff --git a/java/src/game/world/Facing.java b/java/src/game/world/Facing.java index 7cf8302..5035692 100755 --- a/java/src/game/world/Facing.java +++ b/java/src/game/world/Facing.java @@ -2,10 +2,11 @@ package game.world; import java.util.Iterator; import java.util.Map; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; -import game.collect.Iterators; -import game.collect.Maps; import game.properties.IStringSerializable; import game.rng.Random; import game.util.ExtMath; @@ -410,7 +411,7 @@ public enum Facing implements IStringSerializable return this.name; } - public boolean test(Facing p_apply_1_) + public boolean apply(Facing p_apply_1_) { return p_apply_1_ != null && p_apply_1_.getAxis() == this; } @@ -480,7 +481,7 @@ public enum Facing implements IStringSerializable return aenumfacing[rand.zrange(aenumfacing.length)]; } - public boolean test(Facing p_apply_1_) + public boolean apply(Facing p_apply_1_) { return p_apply_1_ != null && p_apply_1_.getAxis().getPlane() == this; } diff --git a/java/src/game/world/Region.java b/java/src/game/world/Region.java index 57a9dd3..3ce8897 100755 --- a/java/src/game/world/Region.java +++ b/java/src/game/world/Region.java @@ -17,9 +17,10 @@ import java.util.Map; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.Block; -import game.collect.Lists; -import game.collect.Maps; import game.entity.Entity; import game.init.BlockRegistry; import game.init.Config; diff --git a/java/src/game/world/Spawner.java b/java/src/game/world/Spawner.java index 943afc9..01d6934 100755 --- a/java/src/game/world/Spawner.java +++ b/java/src/game/world/Spawner.java @@ -2,9 +2,10 @@ package game.world; import java.util.Set; +import com.google.common.collect.Sets; + import game.biome.Biome; import game.block.Block; -import game.collect.Sets; import game.entity.npc.EntityNPC; import game.entity.types.EntityLiving; import game.entity.types.EntityWaterMob; diff --git a/java/src/game/world/State.java b/java/src/game/world/State.java index 8e05fc8..cfca3d6 100755 --- a/java/src/game/world/State.java +++ b/java/src/game/world/State.java @@ -5,15 +5,16 @@ import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; -import java.util.function.Function; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import game.block.Block; -import game.collect.ImmutableMap; -import game.collect.ImmutableTable; -import game.collect.Iterables; -import game.collect.Maps; -import game.collect.StandardTable; -import game.collect.Table; import game.init.BlockRegistry; import game.properties.IProperty; @@ -122,7 +123,7 @@ public class State { throw new IllegalStateException(); } else { - Table table = new StandardTable(); + Table table = HashBasedTable.create(); for(IProperty prop : this.properties.keySet()) { for(Comparable value : prop.getAllowedValues()) { if(value != this.properties.get(prop)) { diff --git a/java/src/game/world/Weather.java b/java/src/game/world/Weather.java index aba3dbf..2a58c47 100755 --- a/java/src/game/world/Weather.java +++ b/java/src/game/world/Weather.java @@ -2,7 +2,8 @@ package game.world; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.rng.Random; import game.rng.RngItem; import game.rng.WeightedList; diff --git a/java/src/game/world/World.java b/java/src/game/world/World.java index 60417ec..5dcaeb1 100755 --- a/java/src/game/world/World.java +++ b/java/src/game/world/World.java @@ -4,7 +4,10 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import game.biome.Biome; import game.block.Block; @@ -14,8 +17,6 @@ import game.block.BlockSlab; import game.block.BlockSnow; import game.block.BlockStairs; import game.block.LeavesType; -import game.collect.Lists; -import game.collect.Sets; import game.dimension.Dimension; import game.entity.Entity; import game.entity.item.EntityExplosion; @@ -556,7 +557,7 @@ public abstract class World implements IWorldAccess { break; List ents = this.getEntitiesInAABBexcluding(entity, new BoundingBox(target, target.add(1, 1, 1)), new Predicate() { - public boolean test(Entity entity) { + public boolean apply(Entity entity) { return entity.canBeCollidedWith(); } }); diff --git a/java/src/game/world/WorldClient.java b/java/src/game/world/WorldClient.java index 2e80eb6..5c9c4f4 100755 --- a/java/src/game/world/WorldClient.java +++ b/java/src/game/world/WorldClient.java @@ -3,13 +3,14 @@ package game.world; import java.util.List; import java.util.Set; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + import game.Game; import game.audio.MovingSoundMinecart; import game.audio.PositionedSound; import game.biome.Biome; import game.block.Block; -import game.collect.Lists; -import game.collect.Sets; import game.dimension.Dimension; import game.entity.Entity; import game.entity.item.EntityCart; diff --git a/java/src/game/world/WorldServer.java b/java/src/game/world/WorldServer.java index 9308493..6e33185 100755 --- a/java/src/game/world/WorldServer.java +++ b/java/src/game/world/WorldServer.java @@ -11,7 +11,11 @@ import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; +import com.google.common.base.Predicate; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import game.Server; import game.biome.Biome; @@ -22,9 +26,6 @@ import game.block.BlockFalling; import game.block.BlockLiquid; import game.block.BlockSnow; import game.clipboard.ClipboardBlock; -import game.collect.Lists; -import game.collect.Maps; -import game.collect.Sets; import game.dimension.Dimension; import game.entity.DamageSource; import game.entity.Entity; @@ -613,7 +614,7 @@ public final class WorldServer extends World { BoundingBox axisalignedbb = (new BoundingBox(blockpos, new BlockPos(blockpos.getX(), World.HEIGHT, blockpos.getZ()))).expand(3.0D, 3.0D, 3.0D); List list = this.getEntitiesWithinAABB(EntityLiving.class, axisalignedbb, new Predicate() { - public boolean test(EntityLiving p_apply_1_) { + public boolean apply(EntityLiving p_apply_1_) { return p_apply_1_ != null && p_apply_1_.isEntityAlive() && WorldServer.this.canSeeSky(p_apply_1_.getPosition()); } }); diff --git a/java/src/game/worldgen/BiomeGenLayered.java b/java/src/game/worldgen/BiomeGenLayered.java index 166a42e..3887249 100755 --- a/java/src/game/worldgen/BiomeGenLayered.java +++ b/java/src/game/worldgen/BiomeGenLayered.java @@ -3,8 +3,9 @@ package game.worldgen; import java.util.List; import java.util.Set; +import com.google.common.collect.Lists; + import game.biome.Biome; -import game.collect.Lists; import game.world.BlockPos; import game.world.LongHashMap; import game.worldgen.layer.GenLayer; diff --git a/java/src/game/worldgen/GeneratorDebug.java b/java/src/game/worldgen/GeneratorDebug.java index b945e86..f88c9ce 100755 --- a/java/src/game/worldgen/GeneratorDebug.java +++ b/java/src/game/worldgen/GeneratorDebug.java @@ -2,8 +2,9 @@ package game.worldgen; import java.util.List; +import com.google.common.collect.Lists; + import game.block.Block; -import game.collect.Lists; import game.init.BlockRegistry; import game.util.ExtMath; import game.world.State; diff --git a/java/src/game/worldgen/feature/WorldGenDesertWells.java b/java/src/game/worldgen/feature/WorldGenDesertWells.java index b0e233d..efd3a36 100755 --- a/java/src/game/worldgen/feature/WorldGenDesertWells.java +++ b/java/src/game/worldgen/feature/WorldGenDesertWells.java @@ -1,11 +1,12 @@ package game.worldgen.feature; +import com.google.common.base.Predicates; + import game.block.BlockSand; import game.block.BlockSlab; import game.init.Blocks; import game.pattern.BlockStateHelper; import game.rng.Random; -import game.util.Predicates; import game.world.BlockPos; import game.world.Facing; import game.world.State; @@ -26,7 +27,7 @@ public class WorldGenDesertWells extends FeatureGenerator position = position.down(); } - if (!field_175913_a.test(worldIn.getState(position))) + if (!field_175913_a.apply(worldIn.getState(position))) { return false; } diff --git a/java/src/game/worldgen/layer/IntCache.java b/java/src/game/worldgen/layer/IntCache.java index 38a4766..c78af63 100755 --- a/java/src/game/worldgen/layer/IntCache.java +++ b/java/src/game/worldgen/layer/IntCache.java @@ -2,7 +2,7 @@ package game.worldgen.layer; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; public class IntCache { diff --git a/java/src/game/worldgen/structure/MapGenStructure.java b/java/src/game/worldgen/structure/MapGenStructure.java index 360f058..05a3bf5 100755 --- a/java/src/game/worldgen/structure/MapGenStructure.java +++ b/java/src/game/worldgen/structure/MapGenStructure.java @@ -3,7 +3,8 @@ package game.worldgen.structure; import java.util.Iterator; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.nbt.NBTBase; import game.nbt.NBTTagCompound; import game.rng.Random; diff --git a/java/src/game/worldgen/structure/MapGenStructureIO.java b/java/src/game/worldgen/structure/MapGenStructureIO.java index 94c185c..cfb3b66 100755 --- a/java/src/game/worldgen/structure/MapGenStructureIO.java +++ b/java/src/game/worldgen/structure/MapGenStructureIO.java @@ -2,7 +2,8 @@ package game.worldgen.structure; import java.util.Map; -import game.collect.Maps; +import com.google.common.collect.Maps; + import game.log.Log; import game.nbt.NBTTagCompound; import game.world.WorldServer; diff --git a/java/src/game/worldgen/structure/MapGenVillage.java b/java/src/game/worldgen/structure/MapGenVillage.java index 9a81a77..80fb684 100755 --- a/java/src/game/worldgen/structure/MapGenVillage.java +++ b/java/src/game/worldgen/structure/MapGenVillage.java @@ -3,8 +3,9 @@ package game.worldgen.structure; import java.util.List; import java.util.Set; +import com.google.common.collect.Sets; + import game.biome.Biome; -import game.collect.Sets; import game.nbt.NBTTagCompound; import game.rng.Random; import game.world.WorldServer; diff --git a/java/src/game/worldgen/structure/StructureBridge.java b/java/src/game/worldgen/structure/StructureBridge.java index a04e30a..bc9a3e0 100755 --- a/java/src/game/worldgen/structure/StructureBridge.java +++ b/java/src/game/worldgen/structure/StructureBridge.java @@ -2,7 +2,8 @@ package game.worldgen.structure; import java.util.List; -import game.collect.Lists; +import com.google.common.collect.Lists; + import game.init.Blocks; import game.nbt.NBTTagCompound; import game.rng.Random; diff --git a/java/src/game/worldgen/structure/StructureStronghold.java b/java/src/game/worldgen/structure/StructureStronghold.java index 6d4f792..46d9fb9 100755 --- a/java/src/game/worldgen/structure/StructureStronghold.java +++ b/java/src/game/worldgen/structure/StructureStronghold.java @@ -3,10 +3,11 @@ package game.worldgen.structure; import java.util.List; import java.util.Map; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + import game.block.BlockSlab; import game.block.BlockStoneBrick; -import game.collect.Lists; -import game.collect.Maps; import game.init.Blocks; import game.init.Items; import game.item.RngLoot; diff --git a/java/src/game/worldgen/structure/StructureVillage.java b/java/src/game/worldgen/structure/StructureVillage.java index 79b793d..9749513 100755 --- a/java/src/game/worldgen/structure/StructureVillage.java +++ b/java/src/game/worldgen/structure/StructureVillage.java @@ -3,6 +3,8 @@ package game.worldgen.structure; import java.util.Iterator; import java.util.List; +import com.google.common.collect.Lists; + import game.biome.Biome; import game.block.Block; import game.block.BlockLog; @@ -10,7 +12,6 @@ import game.block.BlockSandStone; import game.block.BlockSlab; import game.block.BlockStairs; import game.block.BlockTorch; -import game.collect.Lists; import game.color.DyeColor; import game.entity.npc.EntityHuman; import game.init.BlockRegistry; diff --git a/java/src/game/worldgen/tree/WorldGenBigTree.java b/java/src/game/worldgen/tree/WorldGenBigTree.java index 9655450..4cc1f73 100755 --- a/java/src/game/worldgen/tree/WorldGenBigTree.java +++ b/java/src/game/worldgen/tree/WorldGenBigTree.java @@ -2,10 +2,11 @@ package game.worldgen.tree; import java.util.List; +import com.google.common.collect.Lists; + import game.block.Block; import game.block.BlockLeaves; import game.block.BlockLog; -import game.collect.Lists; import game.init.Blocks; import game.material.Material; import game.rng.Random;