[added] Ability to set max size on Bag and Array pools.
[removed] Pool. Replaced all Pool usage with BagPool (which doesn't do a memory copy when items are returned to the pool as Pool's use of ArrayList did).
[changed] TextureAtlas, renamed methods to findRegion and createSprite to better reflect the operation cost.
[removed] IntHashMap and LongHashMap.
[added] ObjectMap, IdentityMap, IntMap, and LongMap. These use open addressing with linear probing to avoid allocation of entry nodes on put. See JGO thread for performance. Changes HashMap usage to ObjectMap.
[removed] LocklessThreadQueue. Replaced by AtomicQueue.
\r
import com.badlogic.gdx.Input;\r
import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
/**\r
* An implementation of the {@link Input} interface for Android.\r
int pointer;\r
}\r
\r
- Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
- @Override public KeyEvent createObject () {\r
+ BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+ protected KeyEvent newObject () {\r
return new KeyEvent();\r
}\r
- }, 1000);\r
-\r
- Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+ };\r
\r
- @Override public TouchEvent createObject () {\r
+ BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+ protected TouchEvent newObject () {\r
return new TouchEvent();\r
}\r
- }, 1000);\r
+ };\r
\r
ArrayList<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
ArrayList<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
case KeyEvent.KEY_TYPED:\r
processor.keyTyped(e.keyChar);\r
}\r
- freeKeyEvents.free(e);\r
+ usedKeyEvents.removeValue(e, true);\r
}\r
\r
len = touchEvents.size();\r
case TouchEvent.TOUCH_DRAGGED:\r
processor.touchDragged(e.x, e.y, e.pointer);\r
}\r
- freeTouchEvents.free(e);\r
+ usedTouchEvents.removeValue(e, true);\r
}\r
} else {\r
int len = touchEvents.size();\r
for (int i = 0; i < len; i++) {\r
TouchEvent e = touchEvents.get(i);\r
// Log.d("AndroidInput", "synch touch: " + (System.nanoTime() - e.timeStamp) / 1000000.0f);\r
- freeTouchEvents.free(e);\r
+ usedTouchEvents.removeValue(e, true);\r
}\r
\r
len = keyEvents.size();\r
for (int i = 0; i < len; i++) {\r
- freeKeyEvents.free(keyEvents.get(i));\r
+ usedKeyEvents.removeValue(keyEvents.get(i), true);\r
}\r
}\r
\r
KeyEvent event = null;\r
switch (e.getAction()) {\r
case android.view.KeyEvent.ACTION_DOWN:\r
- event = freeKeyEvents.newObject();\r
+ event = usedKeyEvents.add();\r
event.keyChar = 0;\r
event.keyCode = e.getKeyCode();\r
event.type = KeyEvent.KEY_DOWN;\r
keys.add(event.keyCode);\r
break;\r
case android.view.KeyEvent.ACTION_UP:\r
- event = freeKeyEvents.newObject();\r
+ event = usedKeyEvents.add();\r
event.keyChar = 0;\r
event.keyCode = e.getKeyCode();\r
event.type = KeyEvent.KEY_UP;\r
keyEvents.add(event);\r
\r
- event = freeKeyEvents.newObject();\r
+ event = usedKeyEvents.add();\r
event.keyChar = character;\r
event.keyCode = 0;\r
event.type = KeyEvent.KEY_TYPED;\r
private void postTouchEvent (AndroidInput input, int type, int x, int y, int pointer) {\r
long timeStamp = System.nanoTime();\r
synchronized (input) {\r
- TouchEvent event = input.freeTouchEvents.newObject();\r
+ TouchEvent event = input.usedTouchEvents.add();\r
event.timeStamp = timeStamp;\r
event.pointer = pointer;\r
event.x = x;\r
private void postTouchEvent (AndroidInput input, int type, int x, int y, int pointer) {\r
long timeStamp = System.nanoTime();\r
synchronized (input) {\r
- TouchEvent event = input.freeTouchEvents.newObject();\r
+ TouchEvent event = input.usedTouchEvents.add();\r
event.timeStamp = timeStamp;\r
event.pointer = 0;\r
event.x = x;\r
\r
import com.badlogic.gdx.Input;\r
import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class JoglInput implements Input, MouseMotionListener, MouseListener, KeyListener {\r
class KeyEvent {\r
int pointer;\r
}\r
\r
- Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
- @Override public KeyEvent createObject () {\r
+ BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+ protected KeyEvent newObject () {\r
return new KeyEvent();\r
}\r
- }, 1000);\r
-\r
- Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+ };\r
\r
- @Override public TouchEvent createObject () {\r
+ BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+ protected TouchEvent newObject () {\r
return new TouchEvent();\r
}\r
- }, 1000);\r
+ };\r
\r
List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
case KeyEvent.KEY_TYPED:\r
processor.keyTyped(e.keyChar);\r
}\r
- freeKeyEvents.free(e);\r
+ usedKeyEvents.removeValue(e, true);\r
}\r
\r
len = touchEvents.size();\r
case TouchEvent.TOUCH_DRAGGED:\r
processor.touchDragged(e.x, e.y, e.pointer);\r
}\r
- freeTouchEvents.free(e);\r
+ usedTouchEvents.removeValue(e, true);\r
}\r
} else {\r
int len = touchEvents.size();\r
for (int i = 0; i < len; i++) {\r
- freeTouchEvents.free(touchEvents.get(i));\r
+ usedTouchEvents.removeValue(touchEvents.get(i), true);\r
}\r
\r
len = keyEvents.size();\r
for (int i = 0; i < len; i++) {\r
- freeKeyEvents.free(keyEvents.get(i));\r
+ usedKeyEvents.removeValue(keyEvents.get(i), true);\r
}\r
}\r
\r
\r
@Override public void mouseDragged (MouseEvent e) {\r
synchronized (this) {\r
- TouchEvent event = freeTouchEvents.newObject();\r
+ TouchEvent event = usedTouchEvents.add();\r
event.pointer = 0;\r
event.x = e.getX();\r
event.y = e.getY();\r
\r
@Override public void mousePressed (MouseEvent e) {\r
synchronized (this) {\r
- TouchEvent event = freeTouchEvents.newObject();\r
+ TouchEvent event = usedTouchEvents.add();\r
event.pointer = 0;\r
event.x = e.getX();\r
event.y = e.getY();\r
\r
@Override public void mouseReleased (MouseEvent e) {\r
synchronized (this) {\r
- TouchEvent event = freeTouchEvents.newObject();\r
+ TouchEvent event = usedTouchEvents.add();\r
event.pointer = 0;\r
event.x = e.getX();\r
event.y = e.getY();\r
\r
@Override public void keyPressed (java.awt.event.KeyEvent e) {\r
synchronized (this) {\r
- KeyEvent event = freeKeyEvents.newObject();\r
+ KeyEvent event = usedKeyEvents.add();\r
event.keyChar = 0;\r
event.keyCode = translateKeyCode(e.getKeyCode());\r
event.type = KeyEvent.KEY_DOWN;\r
\r
@Override public void keyReleased (java.awt.event.KeyEvent e) {\r
synchronized (this) {\r
- KeyEvent event = freeKeyEvents.newObject();\r
+ KeyEvent event = usedKeyEvents.add();\r
event.keyChar = 0;\r
event.keyCode = translateKeyCode(e.getKeyCode());\r
event.type = KeyEvent.KEY_UP;\r
\r
@Override public void keyTyped (java.awt.event.KeyEvent e) {\r
synchronized (this) {\r
- KeyEvent event = freeKeyEvents.newObject();\r
+ KeyEvent event = usedKeyEvents.add();\r
event.keyChar = e.getKeyChar();\r
event.keyCode = 0;\r
event.type = KeyEvent.KEY_TYPED;\r
import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.Input;\r
import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
/**\r
* An implementation of the {@link Input} interface hooking a Jogl panel for input.\r
int pointer;\r
}\r
\r
- Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
- @Override public KeyEvent createObject () {\r
+ BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+ protected KeyEvent newObject () {\r
return new KeyEvent();\r
}\r
- }, 1000);\r
-\r
- Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+ };\r
\r
- @Override public TouchEvent createObject () {\r
+ BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+ protected TouchEvent newObject () {\r
return new TouchEvent();\r
}\r
- }, 1000);\r
+ };\r
\r
List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
case KeyEvent.KEY_TYPED:\r
processor.keyTyped(e.keyChar);\r
}\r
- freeKeyEvents.free(e);\r
+ usedKeyEvents.removeValue(e, true);\r
}\r
\r
len = touchEvents.size();\r
case TouchEvent.TOUCH_DRAGGED:\r
processor.touchDragged(e.x, e.y, e.pointer);\r
}\r
- freeTouchEvents.free(e);\r
+ usedTouchEvents.removeValue(e, true);\r
}\r
} else {\r
int len = touchEvents.size();\r
for (int i = 0; i < len; i++) {\r
- freeTouchEvents.free(touchEvents.get(i));\r
+ usedTouchEvents.removeValue(touchEvents.get(i), true);\r
}\r
\r
len = keyEvents.size();\r
for (int i = 0; i < len; i++) {\r
- freeKeyEvents.free(keyEvents.get(i));\r
+ usedKeyEvents.removeValue(keyEvents.get(i), true);\r
}\r
}\r
\r
if (isButtonPressed()) {\r
if (mousePressed == false) {\r
mousePressed = true;\r
- TouchEvent event = freeTouchEvents.newObject();\r
+ TouchEvent event = usedTouchEvents.add();\r
event.x = x;\r
event.y = y;\r
event.pointer = 0;\r
mouseY = y;\r
} else {\r
if (mouseX != x || mouseY != y) {\r
- TouchEvent event = freeTouchEvents.newObject();\r
+ TouchEvent event = usedTouchEvents.add();\r
event.x = x;\r
event.y = y;\r
event.pointer = 0;\r
mouseX = x;\r
mouseY = y;\r
mousePressed = false;\r
- TouchEvent event = freeTouchEvents.newObject();\r
+ TouchEvent event = usedTouchEvents.add();\r
event.x = x;\r
event.y = y;\r
event.pointer = 0;\r
int keyCode = getGdxKeyCode(Keyboard.getEventKey());\r
char keyChar = Keyboard.getEventCharacter();\r
\r
- KeyEvent event = freeKeyEvents.newObject();\r
+ KeyEvent event = usedKeyEvents.add();\r
event.keyCode = keyCode;\r
event.keyChar = 0;\r
event.type = KeyEvent.KEY_DOWN;\r
keyEvents.add(event);\r
\r
- event = freeKeyEvents.newObject();\r
+ event = usedKeyEvents.add();\r
event.keyCode = 0;\r
event.keyChar = keyChar;\r
event.type = KeyEvent.KEY_TYPED;\r
} else {\r
int keyCode = LwjglInput.getGdxKeyCode(Keyboard.getEventKey());\r
\r
- KeyEvent event = freeKeyEvents.newObject();\r
+ KeyEvent event = usedKeyEvents.add();\r
event.keyCode = keyCode;\r
event.keyChar = 0;\r
event.type = KeyEvent.KEY_UP;\r
import com.badlogic.anglejni.ESLoop;\r
import com.badlogic.gdx.Input;\r
import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class AngleInput implements Input {\r
\r
int pointer;\r
}\r
\r
- Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
- @Override public KeyEvent createObject () {\r
+ BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+ protected KeyEvent newObject () {\r
return new KeyEvent();\r
}\r
- }, 1000);\r
-\r
- Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+ };\r
\r
- @Override public TouchEvent createObject () {\r
+ BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+ protected TouchEvent newObject () {\r
return new TouchEvent();\r
}\r
- }, 1000);\r
+ };\r
\r
List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
case KeyEvent.KEY_TYPED:\r
processor.keyTyped(e.keyChar);\r
}\r
- freeKeyEvents.free(e);\r
+ usedKeyEvents.removeValue(e, true);\r
}\r
\r
len = touchEvents.size();\r
case TouchEvent.TOUCH_DRAGGED:\r
processor.touchDragged(e.x, e.y, e.pointer);\r
}\r
- freeTouchEvents.free(e);\r
+ usedTouchEvents.removeValue(e, true);\r
}\r
} else {\r
int len = touchEvents.size();\r
for (int i = 0; i < len; i++) {\r
- freeTouchEvents.free(touchEvents.get(i));\r
+ usedTouchEvents.removeValue(touchEvents.get(i), true);\r
}\r
\r
len = keyEvents.size();\r
for (int i = 0; i < len; i++) {\r
- freeKeyEvents.free(keyEvents.get(i));\r
+ usedKeyEvents.removeValue(keyEvents.get(i), true);\r
}\r
}\r
\r
\r
void registerKeyEvent (int action, int key, int uniCode) {\r
synchronized (this) {\r
- KeyEvent event = freeKeyEvents.newObject();\r
+ KeyEvent event = usedKeyEvents.add();\r
event.keyChar = (char)uniCode;\r
event.keyCode = translateKey(key);\r
\r
if (button != 1) return;\r
\r
synchronized (this) {\r
- TouchEvent event = freeTouchEvents.newObject();\r
+ TouchEvent event = usedTouchEvents.add();\r
event.x = x;\r
event.y = y;\r
event.pointer = 0;\r
\r
int type = Integer.parseInt(reader.readLine());\r
String textureId = reader.readLine();\r
- TextureRegion region = atlas.getRegion(textureId);\r
+ TextureRegion region = atlas.findRegion(textureId);\r
float u = region.getU();\r
float v = region.getV();\r
\r
\r
int type = Integer.parseInt(reader.readLine());\r
String textureId = reader.readLine();\r
- TextureRegion region = atlas.getRegion(textureId);\r
+ TextureRegion region = atlas.findRegion(textureId);\r
float u = region.getU();\r
float v = region.getV();\r
\r
package com.badlogic.gdx.twl;\r
\r
import de.matthiasmann.twl.DialogLayout;\r
+import de.matthiasmann.twl.Event;\r
import de.matthiasmann.twl.Widget;\r
\r
/**\r
* @author Nathan Sweet\r
*/\r
public class Layout extends DialogLayout {\r
+ private boolean eatEvents;\r
+\r
public Layout () {\r
setTheme("");\r
}\r
setTheme(theme);\r
}\r
\r
+ public Layout (boolean eatEvents) {\r
+ this.eatEvents = eatEvents;\r
+ }\r
+\r
+ public Layout (String theme, boolean eatEvents) {\r
+ setTheme(theme);\r
+ this.eatEvents = eatEvents;\r
+ }\r
+\r
+ protected boolean handleEvent (Event evt) {\r
+ return eatEvents;\r
+ }\r
+\r
public Direction horizontal () {\r
return new Direction(true);\r
}\r
import java.io.IOException;
import java.net.URL;
-import java.util.HashMap;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.BitmapFont;
+import com.badlogic.gdx.utils.ObjectMap;
import de.matthiasmann.twl.renderer.CacheContext;
*/
class GdxCacheContext implements CacheContext {
final GdxRenderer renderer;
- private final HashMap<String, GdxTexture> textures = new HashMap();
- private final HashMap<String, BitmapFont> fonts = new HashMap();
+ private final ObjectMap<String, GdxTexture> textures = new ObjectMap();
+ private final ObjectMap<String, BitmapFont> fonts = new ObjectMap();
private boolean valid = true;
GdxCacheContext (GdxRenderer renderer) {
* should be cached rather than calling this method multiple times.\r
* @return The region, or null.\r
*/\r
- public AtlasRegion getRegion (String name) {\r
+ public AtlasRegion findRegion (String name) {\r
for (int i = 0, n = regions.size(); i < n; i++)\r
if (regions.get(i).name.equals(name)) return regions.get(i);\r
return null;\r
* the result should be cached rather than calling this method multiple times.\r
* @return The region, or null.\r
*/\r
- public AtlasRegion getRegion (String name, int index) {\r
+ public AtlasRegion findRegion (String name, int index) {\r
for (int i = 0, n = regions.size(); i < n; i++) {\r
AtlasRegion region = regions.get(i);\r
if (!region.name.equals(name)) continue;\r
* Returns all regions with the specified name, ordered by smallest to largest {@link AtlasRegion#index index}. This method\r
* uses string comparison to find the regions, so the result should be cached rather than calling this method multiple times.\r
*/\r
- public List<AtlasRegion> getRegions (String name) {\r
+ public List<AtlasRegion> findRegions (String name) {\r
ArrayList<AtlasRegion> matched = new ArrayList();\r
for (int i = 0, n = regions.size(); i < n; i++) {\r
AtlasRegion region = regions.get(i);\r
/**\r
* Returns all regions in the atlas as sprites. This method creates a new sprite for each region, so the result should be\r
* stored rather than calling this method multiple times.\r
- * @see #getSprite(String)\r
+ * @see #createSprite(String)\r
*/\r
- public List<Sprite> getSprites () {\r
+ public List<Sprite> createSprites () {\r
ArrayList sprites = new ArrayList(regions.size());\r
for (int i = 0, n = regions.size(); i < n; i++)\r
sprites.add(newSprite(regions.get(i)));\r
* find the region and constructs a new sprite, so the result should be cached rather than calling this method multiple times.\r
* @return The sprite, or null.\r
*/\r
- public Sprite getSprite (String name) {\r
+ public Sprite createSprite (String name) {\r
for (int i = 0, n = regions.size(); i < n; i++)\r
if (regions.get(i).name.equals(name)) return newSprite(regions.get(i));\r
return null;\r
* Returns the first region found with the specified name and index as a sprite. This method uses string comparison to find the\r
* region and constructs a new sprite, so the result should be cached rather than calling this method multiple times.\r
* @return The sprite, or null.\r
- * @see #getSprite(String)\r
+ * @see #createSprite(String)\r
*/\r
- public Sprite getSprite (String name, int index) {\r
+ public Sprite createSprite (String name, int index) {\r
for (int i = 0, n = regions.size(); i < n; i++) {\r
AtlasRegion region = regions.get(i);\r
if (!region.name.equals(name)) continue;\r
* Returns all regions with the specified name as sprites, ordered by smallest to largest {@link AtlasRegion#index index}. This\r
* method uses string comparison to find the regions and constructs new sprites, so the result should be cached rather than\r
* calling this method multiple times.\r
- * @see #getSprite(String)\r
+ * @see #createSprite(String)\r
*/\r
- public List<Sprite> getSprites (String name) {\r
+ public List<Sprite> createSprites (String name) {\r
ArrayList<Sprite> matched = new ArrayList();\r
for (int i = 0, n = regions.size(); i < n; i++) {\r
AtlasRegion region = regions.get(i);\r
* <br>\r
* When sprites are packed, if the original file name ends with a number, it is stored as the index and is not considered as\r
* part of the sprite's name. This is useful for keeping animation frames in order.\r
- * @see TextureAtlas#getRegions(String)\r
+ * @see TextureAtlas#findRegions(String)\r
*/\r
public int index;\r
\r
import com.badlogic.gdx.graphics.Mesh;\r
import com.badlogic.gdx.math.Matrix3;\r
import com.badlogic.gdx.math.Matrix4;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
\r
/**\r
* <p>\r
private boolean isCompiled;\r
\r
/** uniform lookup **/\r
- private final HashMap<String, Integer> uniforms = new HashMap<String, Integer>();\r
+ private final ObjectMap<String, Integer> uniforms = new ObjectMap<String, Integer>();\r
\r
/** attribute lookup **/\r
- private final HashMap<String, Integer> attributes = new HashMap<String, Integer>();\r
+ private final ObjectMap<String, Integer> attributes = new ObjectMap<String, Integer>();\r
\r
/** program handle **/\r
private int program;\r
\r
import java.io.DataInputStream;\r
import java.io.DataOutputStream;\r
-import java.util.HashMap;\r
\r
-import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.graphics.GL10;\r
import com.badlogic.gdx.graphics.Material;\r
import com.badlogic.gdx.graphics.Mesh;\r
import com.badlogic.gdx.graphics.VertexAttributes;\r
-import com.badlogic.gdx.utils.GdxRuntimeException;\r
import com.badlogic.gdx.graphics.animation.Animator;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Animation;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Animator;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Model;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Renderer;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
\r
/**\r
* An animated model with {@link KeyframeAnimation}s. Currently the animations can only be instanced from an {@link MD5Animation}.\r
public class KeyframedModel {\r
\r
private Material[] mMaterials;\r
- private HashMap<String, KeyframeAnimation> mAnimations = new HashMap<String, KeyframeAnimation>();\r
+ private ObjectMap<String, KeyframeAnimation> mAnimations = new ObjectMap<String, KeyframeAnimation>();\r
private KeyframeAnimator mAnimator = null;\r
private Mesh[] mTarget = null;\r
private int mNumMeshes = 0;\r
String imageName = new File(imagePath.replace('\\', '/')).getName();\r
int lastDotIndex = imageName.lastIndexOf('.');\r
if (lastDotIndex != -1) imageName = imageName.substring(0, lastDotIndex);\r
- Sprite sprite = atlas.getSprite(imageName);\r
+ Sprite sprite = atlas.createSprite(imageName);\r
if (sprite == null) throw new IllegalArgumentException("SpriteSheet missing image: " + imageName);\r
emitter.setSprite(sprite);\r
}\r
*/\r
package com.badlogic.gdx.graphics.texturedict;\r
\r
-import java.util.HashMap;\r
-import java.util.Map.Entry;\r
-\r
-import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.Files.FileType;\r
+import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.files.FileHandle;\r
import com.badlogic.gdx.graphics.Texture;\r
import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
\r
/**\r
* <p>\r
*/\r
public class TextureDict {\r
\r
- private static HashMap<String, TextureRef> sDictionary = new HashMap<String, TextureRef>();\r
+ private static ObjectMap<String, TextureRef> sDictionary = new ObjectMap<String, TextureRef>();\r
\r
/**\r
* Loads a new texture into the dictionary as a reference counted {@link TextureRef}.\r
import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;\r
import com.badlogic.gdx.physics.box2d.joints.WeldJoint;\r
import com.badlogic.gdx.physics.box2d.joints.WeldJointDef;\r
-import com.badlogic.gdx.utils.LongHashMap;\r
+import com.badlogic.gdx.utils.LongMap;\r
\r
/**\r
* The world class manages all physics entities, dynamic simulation, and asynchronous queries. The world also contains efficient\r
private final long addr;\r
\r
/** all known bodies **/\r
- protected final LongHashMap<Body> bodies = new LongHashMap<Body>(100);\r
+ protected final LongMap<Body> bodies = new LongMap<Body>(100);\r
\r
/** all known fixtures **/\r
- protected final LongHashMap<Fixture> fixtures = new LongHashMap<Fixture>(100);\r
+ protected final LongMap<Fixture> fixtures = new LongMap<Fixture>(100);\r
\r
/** all known joints **/\r
- protected final LongHashMap<Joint> joints = new LongHashMap<Joint>(100);\r
+ protected final LongMap<Joint> joints = new LongMap<Joint>(100);\r
\r
/** Contact filter **/\r
protected ContactFilter contactFilter = null;\r
\r
import java.util.ArrayList;\r
import java.util.Collections;\r
-import java.util.HashMap;\r
import java.util.List;\r
-import java.util.Map;\r
\r
import com.badlogic.gdx.Files.FileType;\r
import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.math.Matrix3;\r
import com.badlogic.gdx.math.Matrix4;\r
import com.badlogic.gdx.math.Vector2;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
\r
/**\r
* A group is an Actor that contains other Actors (also other Groups which are Actors).\r
protected final List<Actor> immutableChildren;\r
protected final List<Group> groups; // TODO O(n) delete, baad.\r
protected final List<Group> immutableGroups;\r
- protected final Map<String, Actor> namesToActors;\r
+ protected final ObjectMap<String, Actor> namesToActors;\r
\r
public Actor lastTouchedChild;\r
public Actor focusedActor = null;\r
this.immutableChildren = Collections.unmodifiableList(this.children);\r
this.groups = new ArrayList<Group>();\r
this.immutableGroups = Collections.unmodifiableList(this.groups);\r
- this.namesToActors = new HashMap<String, Actor>();\r
+ this.namesToActors = new ObjectMap<String, Actor>();\r
}\r
\r
protected void updateTransform () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class Delay implements Action {\r
- static final Pool<Delay> pool = new Pool<Delay>(new PoolObjectFactory<Delay>() {\r
- @Override public Delay createObject () {\r
+ static final BagPool<Delay> pool = new BagPool<Delay>(4, 100) {\r
+ protected Delay newObject () {\r
return new Delay();\r
}\r
- }, 100);\r
+ };\r
\r
protected float taken;\r
protected float duration;\r
protected Action action;\r
\r
public static Delay $ (Action action, float duration) {\r
- Delay delay = pool.newObject();\r
+ Delay delay = pool.add();\r
delay.duration = duration;\r
delay.action = action;\r
return delay;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class FadeIn implements Action {\r
- static final Pool<FadeIn> pool = new Pool<FadeIn>(new PoolObjectFactory<FadeIn>() {\r
- @Override public FadeIn createObject () {\r
+ static final BagPool<FadeIn> pool = new BagPool<FadeIn>(4, 100) {\r
+ protected FadeIn newObject () {\r
return new FadeIn();\r
}\r
- }, 100);\r
+ };\r
\r
protected float startAlpha = 0;\r
protected float deltaAlpha = 0;\r
protected boolean done;\r
\r
public static FadeIn $ (float duration) {\r
- FadeIn action = pool.newObject();\r
+ FadeIn action = pool.add();\r
action.duration = duration;\r
action.invDuration = 1 / duration;\r
return action;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class FadeOut implements Action {\r
- static final Pool<FadeOut> pool = new Pool<FadeOut>(new PoolObjectFactory<FadeOut>() {\r
- @Override public FadeOut createObject () {\r
+ static final BagPool<FadeOut> pool = new BagPool<FadeOut>(4, 100) {\r
+ protected FadeOut newObject () {\r
return new FadeOut();\r
}\r
- }, 100);\r
+ };\r
\r
protected float startAlpha = 0;\r
protected float deltaAlpha = 0;\r
protected boolean done;\r
\r
public static FadeOut $ (float duration) {\r
- FadeOut action = pool.newObject();\r
+ FadeOut action = pool.add();\r
action.duration = duration;\r
action.invDuration = 1 / duration;\r
return action;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class FadeTo implements Action {\r
- static final Pool<FadeTo> pool = new Pool<FadeTo>(new PoolObjectFactory<FadeTo>() {\r
- @Override public FadeTo createObject () {\r
+ static final BagPool<FadeTo> pool = new BagPool<FadeTo>(4, 100) {\r
+ protected FadeTo newObject () {\r
return new FadeTo();\r
}\r
- }, 100);\r
+ };\r
\r
protected float toAlpha = 0;\r
protected float startAlpha;\r
protected boolean done;\r
\r
public static FadeTo $ (float alpha, float duration) {\r
- FadeTo action = pool.newObject();\r
+ FadeTo action = pool.add();\r
if (alpha < 0) alpha = 0;\r
if (alpha > 1) alpha = 1;\r
action.toAlpha = alpha;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class Forever implements Action {\r
- static final Pool<Forever> pool = new Pool<Forever>(new PoolObjectFactory<Forever>() {\r
- @Override public Forever createObject () {\r
+ static final BagPool<Forever> pool = new BagPool<Forever>(4, 100) {\r
+ protected Forever newObject () {\r
return new Forever();\r
}\r
- }, 100);\r
+ };\r
\r
protected Action action;\r
protected Actor target;\r
\r
public static Forever $ (Action action) {\r
- Forever forever = pool.newObject();\r
+ Forever forever = pool.add();\r
forever.action = action;\r
return forever;\r
}\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
action.finish();\r
}\r
\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class MoveBy implements Action {\r
- static final Pool<MoveBy> pool = new Pool<MoveBy>(new PoolObjectFactory<MoveBy>() {\r
- @Override public MoveBy createObject () {\r
+ static final BagPool<MoveBy> pool = new BagPool<MoveBy>(4, 100) {\r
+ protected MoveBy newObject () {\r
return new MoveBy();\r
}\r
- }, 100);\r
+ };\r
\r
protected float x;\r
protected float y;\r
protected boolean done;\r
\r
public static MoveBy $ (float x, float y, float duration) {\r
- MoveBy action = pool.newObject();\r
+ MoveBy action = pool.add();\r
action.x = x;\r
action.y = y;\r
action.duration = duration;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class MoveTo implements Action {\r
- static final Pool<MoveTo> pool = new Pool<MoveTo>(new PoolObjectFactory<MoveTo>() {\r
- @Override public MoveTo createObject () {\r
+ static final BagPool<MoveTo> pool = new BagPool<MoveTo>(4, 100) {\r
+ protected MoveTo newObject () {\r
return new MoveTo();\r
}\r
- }, 100);\r
+ };\r
\r
protected float x;\r
protected float y;\r
protected boolean done;\r
\r
public static MoveTo $ (float x, float y, float duration) {\r
- MoveTo action = pool.newObject();\r
+ MoveTo action = pool.add();\r
action.x = x;\r
action.y = y;\r
action.duration = duration;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class Parallel implements Action {\r
- static final Pool<Parallel> pool = new Pool<Parallel>(new PoolObjectFactory<Parallel>() {\r
- @Override public Parallel createObject () {\r
+ static final BagPool<Parallel> pool = new BagPool<Parallel>(4, 100) {\r
+ protected Parallel newObject () {\r
return new Parallel();\r
}\r
- }, 100);\r
+ };\r
\r
public static Parallel $ (Action... actions) {\r
- Parallel action = pool.newObject();\r
+ Parallel action = pool.add();\r
action.actions.clear();\r
int len = actions.length;\r
for (int i = 0; i < len; i++)\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
int len = 0;\r
for (int i = 0; i < len; i++)\r
actions.get(i).finish();\r
}\r
\r
@Override public Action copy () {\r
- Parallel action = pool.newObject();\r
+ Parallel action = pool.add();\r
action.actions.clear();\r
int len = actions.size();\r
for (int i = 0; i < len; i++)\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class Repeat implements Action {\r
- static final Pool<Repeat> pool = new Pool<Repeat>(new PoolObjectFactory<Repeat>() {\r
- @Override public Repeat createObject () {\r
+ static final BagPool<Repeat> pool = new BagPool<Repeat>(4, 100) {\r
+ protected Repeat newObject () {\r
return new Repeat();\r
}\r
- }, 100);\r
+ };\r
\r
protected Action action;\r
protected Actor target;\r
protected int finishedTimes;\r
\r
public static Repeat $ (Action action, int times) {\r
- Repeat repeat = pool.newObject();\r
+ Repeat repeat = pool.add();\r
repeat.action = action;\r
repeat.times = times;\r
repeat.finishedTimes = 0;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
action.finish();\r
}\r
\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class RotateBy implements Action {\r
- static final Pool<RotateBy> pool = new Pool<RotateBy>(new PoolObjectFactory<RotateBy>() {\r
- @Override public RotateBy createObject () {\r
+ static final BagPool<RotateBy> pool = new BagPool<RotateBy>(4, 100) {\r
+ protected RotateBy newObject () {\r
return new RotateBy();\r
}\r
- }, 100);\r
+ };\r
\r
protected float rotation;\r
protected float startRotation;;\r
protected boolean done;\r
\r
public static RotateBy $ (float rotation, float duration) {\r
- RotateBy action = pool.newObject();\r
+ RotateBy action = pool.add();\r
action.rotation = rotation;\r
action.duration = duration;\r
action.invDuration = 1 / duration;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class RotateTo implements Action {\r
- static final Pool<RotateTo> pool = new Pool<RotateTo>(new PoolObjectFactory<RotateTo>() {\r
- @Override public RotateTo createObject () {\r
+ static final BagPool<RotateTo> pool = new BagPool<RotateTo>(4, 100) {\r
+ protected RotateTo newObject () {\r
return new RotateTo();\r
}\r
- }, 100);\r
+ };\r
\r
protected float rotation;\r
protected float startRotation;;\r
protected boolean done;\r
\r
public static RotateTo $ (float rotation, float duration) {\r
- RotateTo action = pool.newObject();\r
+ RotateTo action = pool.add();\r
action.rotation = rotation;\r
action.duration = duration;\r
action.invDuration = 1 / duration;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class ScaleTo implements Action {\r
- static final Pool<ScaleTo> pool = new Pool<ScaleTo>(new PoolObjectFactory<ScaleTo>() {\r
- @Override public ScaleTo createObject () {\r
+ static final BagPool<ScaleTo> pool = new BagPool<ScaleTo>(4, 100) {\r
+ protected ScaleTo newObject () {\r
return new ScaleTo();\r
}\r
- }, 100);\r
+ };\r
\r
protected float scaleX;\r
protected float scaleY;\r
protected boolean done;\r
\r
public static ScaleTo $ (float scaleX, float scaleY, float duration) {\r
- ScaleTo action = pool.newObject();\r
+ ScaleTo action = pool.add();\r
action.scaleX = scaleX;\r
action.scaleY = scaleY;\r
action.duration = duration;\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
}\r
\r
@Override public Action copy () {\r
\r
import com.badlogic.gdx.scenes.scene2d.Action;\r
import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
\r
public class Sequence implements Action {\r
- static final Pool<Sequence> pool = new Pool<Sequence>(new PoolObjectFactory<Sequence>() {\r
- @Override public Sequence createObject () {\r
+ static final BagPool<Sequence> pool = new BagPool<Sequence>(4, 100) {\r
+ protected Sequence newObject () {\r
return new Sequence();\r
}\r
- }, 100);\r
+ };\r
\r
protected final List<Action> actions = new ArrayList<Action>();\r
protected Actor target;\r
protected int currAction = 0;\r
\r
public static Sequence $ (Action... actions) {\r
- Sequence action = pool.newObject();\r
+ Sequence action = pool.add();\r
action.actions.clear();\r
int len = actions.length;\r
for (int i = 0; i < len; i++)\r
}\r
\r
@Override public void finish () {\r
- pool.free(this);\r
+ pool.removeValue(this, true);\r
int len = 0;\r
for (int i = 0; i < len; i++)\r
actions.get(i).finish();\r
}\r
\r
@Override public Action copy () {\r
- Sequence action = pool.newObject();\r
+ Sequence action = pool.add();\r
action.actions.clear();\r
int len = actions.size();\r
for (int i = 0; i < len; i++)\r
abstract public class ArrayPool<T> implements Iterable<T> {\r
public T[] items;\r
public int size;\r
+ public final int max;\r
\r
private ItemIterator iterator;\r
\r
}\r
\r
public ArrayPool (int capacity) {\r
+ this(capacity, -1);\r
+ }\r
+\r
+ /**\r
+ * @param max The maximum size of this pool. See {@link #add()}.\r
+ */\r
+ public ArrayPool (int capacity, int max) {\r
+ this.max = max;\r
this.items = (T[])new Object[capacity];\r
}\r
\r
* Creates a new array with {@link #items} of the specified type.\r
*/\r
public ArrayPool (Class<T> arrayType, int capacity) {\r
+ this(arrayType, capacity, -1);\r
+ }\r
+\r
+ /**\r
+ * Creates a new array with {@link #items} of the specified type.\r
+ * @param max The maximum size of this pool. See {@link #add()}.\r
+ */\r
+ public ArrayPool (Class<T> arrayType, int capacity, int max) {\r
+ this.max = max;\r
items = (T[])java.lang.reflect.Array.newInstance(arrayType, capacity);\r
}\r
\r
abstract protected T newObject ();\r
\r
+ /**\r
+ * Returns an object from this pool. The object may be new (from {@link #newObject()}) or reused (previously\r
+ * {@link #removeValue(Object, boolean) removed} from the pool). If this pool already contains {@link #max} objects, a new\r
+ * object is returned, but it is not added to the pool (it will be garbage collected).\r
+ */\r
public T add () {\r
+ if (size == max) return newObject();\r
T[] items = this.items;\r
if (size == items.length) {\r
T item = newObject();\r
abstract public class BagPool<T> implements Iterable<T> {\r
public T[] items;\r
public int size;\r
+ public final int max;\r
\r
private ItemIterator iterator;\r
\r
}\r
\r
public BagPool (int capacity) {\r
+ this(capacity, -1);\r
+ }\r
+\r
+ /**\r
+ * @param max The maximum size of this pool. See {@link #add()}.\r
+ */\r
+ public BagPool (int capacity, int max) {\r
+ this.max = max;\r
items = (T[])new Object[capacity];\r
}\r
\r
* Creates a new bag with {@link #items} of the specified type.\r
*/\r
public BagPool (Class<T> arrayType, int capacity) {\r
+ this(arrayType, capacity, -1);\r
+ }\r
+\r
+ /**\r
+ * Creates a new bag with {@link #items} of the specified type.\r
+ * @param max The maximum size of this pool. See {@link #add()}.\r
+ */\r
+ public BagPool (Class<T> arrayType, int capacity, int max) {\r
+ this.max = max;\r
items = (T[])java.lang.reflect.Array.newInstance(arrayType, capacity);\r
}\r
\r
abstract protected T newObject ();\r
\r
+ /**\r
+ * Returns an object from this pool. The object may be new (from {@link #newObject()}) or reused (previously\r
+ * {@link #removeValue(Object, boolean) removed} from the pool). If this pool already contains {@link #max} objects, a new\r
+ * object is returned, but it is not added to the pool (it will be garbage collected).\r
+ */\r
public T add () {\r
+ if (size == max) return newObject();\r
if (size == items.length) {\r
T item = newObject();\r
resize((int)(size * 1.75f), false)[size++] = item;\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Iterator;\r
+\r
+import com.badlogic.gdx.utils.ObjectMap.Entry;\r
+\r
+/**\r
+ * An unordered map that uses int keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put.<br>\r
+ * <br>\r
+ * Warning: null cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class IdentityMap<K, V> {\r
+ static private final int EXTRA = 4;\r
+\r
+ public int size;\r
+\r
+ K[] keyTable;\r
+ V[] valueTable;\r
+ private float loadFactor;\r
+ private int mask, capacity, threshold;\r
+ private Entries entries;\r
+ private Values values;\r
+ private Keys keys;\r
+\r
+ public IdentityMap () {\r
+ this(16, 0.75f);\r
+ }\r
+\r
+ public IdentityMap (int initialCapacity) {\r
+ this(initialCapacity, 0.75f);\r
+ }\r
+\r
+ public IdentityMap (int initialCapacity, float loadFactor) {\r
+ if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+ if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+ this.loadFactor = loadFactor;\r
+ threshold = (int)(capacity * loadFactor);\r
+ keyTable = (K[])new Object[capacity + EXTRA];\r
+ valueTable = (V[])new Object[capacity + EXTRA];\r
+ mask = capacity - 1;\r
+ }\r
+\r
+ public V put (K key, V value) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = System.identityHashCode(key) & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null || existingKey == key) break;\r
+ index++;\r
+ }\r
+ keyTable[index] = key;\r
+ V oldValue = valueTable[index];\r
+ valueTable[index] = value;\r
+ if (size++ >= threshold || keyTable[keyTable.length - 1] != null) resize(capacity << 1);\r
+ return oldValue;\r
+ }\r
+\r
+ public void putAll (IdentityMap<K, V> map) {\r
+ ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+ for (Entry<K, V> entry : map.entries())\r
+ put(entry.key, entry.value);\r
+ }\r
+\r
+ public V get (K key) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = System.identityHashCode(key) & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null) return null;\r
+ if (existingKey == key) return valueTable[index];\r
+ index++;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+ * an expensive operation.\r
+ */\r
+ public boolean containsValue (Object value, boolean identity) {\r
+ V[] valueTable = this.valueTable;\r
+ if (value == null) {\r
+ K[] keyTable = this.keyTable;\r
+ for (int i = keyTable.length; i-- > 0;)\r
+ if (keyTable[i] != null && valueTable[i] == null) return true;\r
+ } else if (identity) {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (valueTable[i] == value) return true;\r
+ } else {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (value.equals(valueTable[i])) return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean containsKey (K key) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = System.identityHashCode(key) & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null) return false;\r
+ if (existingKey == key) return true;\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public V remove (K key) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = System.identityHashCode(key) & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null) return null;\r
+ if (existingKey == key) {\r
+ keyTable[index] = null;\r
+ V value = valueTable[index];\r
+ valueTable[index] = null;\r
+ return value;\r
+ }\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public void clear () {\r
+ K[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = keyTable.length; i-- > 0;) {\r
+ if (keyTable[i] != null) {\r
+ keyTable[i] = null;\r
+ valueTable[i] = null;\r
+ }\r
+ }\r
+ size = 0;\r
+ }\r
+\r
+ /**\r
+ * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+ * items to avoid multiple backing array resizes.\r
+ */\r
+ public void ensureCapacity (int additionalCapacity) {\r
+ int sizeNeeded = size + additionalCapacity;\r
+ if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+ }\r
+\r
+ private void resize (int newSize) {\r
+ int newMask = newSize - 1;\r
+ mask = newMask;\r
+ capacity = newSize;\r
+ threshold = (int)(newSize * loadFactor);\r
+\r
+ newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+ K[] newKeyTable = (K[])new Object[newSize];\r
+ V[] newValueTable = (V[])new Object[newSize];\r
+\r
+ K[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = 0, n = keyTable.length; i < n; i++) {\r
+ K key = keyTable[i];\r
+ if (key != null) {\r
+ int index = System.identityHashCode(key) & newMask;\r
+ while (true) {\r
+ if (newKeyTable[index] == null) break;\r
+ index++;\r
+ }\r
+ if (index == newSize) {\r
+ // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+ resize(capacity << 1);\r
+ return;\r
+ }\r
+ newKeyTable[index] = key;\r
+ newValueTable[index] = valueTable[i];\r
+ }\r
+ }\r
+ this.keyTable = newKeyTable;\r
+ this.valueTable = newValueTable;\r
+ }\r
+\r
+ public String toString () {\r
+ if (size == 0) return "[]";\r
+ StringBuilder buffer = new StringBuilder(32);\r
+ buffer.append('[');\r
+\r
+ K[] keyTable = this.keyTable;\r
+ int i = keyTable.length;\r
+ while (i-- > 0) {\r
+ K key = keyTable[i];\r
+ if (key == null) continue;\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ break;\r
+ }\r
+ while (i-- > 0) {\r
+ K key = keyTable[i];\r
+ if (key == null) continue;\r
+ buffer.append(", ");\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ }\r
+ buffer.append(']');\r
+ return buffer.toString();\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+ * time this method is called.\r
+ */\r
+ public Entries<K, V> entries () {\r
+ if (entries == null)\r
+ entries = new Entries(this);\r
+ else\r
+ entries.reset();\r
+ return entries;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Values<V> values () {\r
+ if (values == null)\r
+ values = new Values(this);\r
+ else\r
+ values.reset();\r
+ return values;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Keys<K> keys () {\r
+ if (keys == null)\r
+ keys = new Keys(this);\r
+ else\r
+ keys.reset();\r
+ return keys;\r
+ }\r
+\r
+ static public class Entry<K, V> {\r
+ public K key;\r
+ public V value;\r
+\r
+ public String toString () {\r
+ return key + "=" + value;\r
+ }\r
+ }\r
+\r
+ static public class Entries<K, V> implements Iterable<Entry<K, V>>, Iterator<Entry<K, V>> {\r
+ Entry<K, V> entry = new Entry();\r
+ int index = -1;\r
+ private final IdentityMap map;\r
+\r
+ public Entries (IdentityMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ Object[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != null) return true;\r
+ return false;\r
+ }\r
+\r
+ public Entry<K, V> next () {\r
+ entry.key = (K)map.keyTable[index];\r
+ entry.value = (V)map.valueTable[index];\r
+ return entry;\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = null;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<Entry<K, V>> iterator () {\r
+ return this;\r
+ }\r
+ }\r
+\r
+ static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+ int index = -1;\r
+ private final IdentityMap map;\r
+\r
+ public Values (IdentityMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ Object[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != null) return true;\r
+ return false;\r
+ }\r
+\r
+ public V next () {\r
+ return (V)map.valueTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = null;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<V> iterator () {\r
+ return this;\r
+ }\r
+\r
+ public Array<V> toArray () {\r
+ Array array = new Array(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+\r
+ static public class Keys<K> implements Iterable<K>, Iterator<K> {\r
+ int index = -1;\r
+ private final IdentityMap map;\r
+\r
+ public Keys (IdentityMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ Object[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != null) return true;\r
+ return false;\r
+ }\r
+\r
+ public K next () {\r
+ return (K)map.keyTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = null;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<K> iterator () {\r
+ return this;\r
+ }\r
+\r
+ public Array<K> toArray () {\r
+ Array array = new Array(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.Iterator;\r
-\r
-/**\r
- * An unordered map that uses int keys. Avoids the boxing that occurs with HashMap<Integer, T>.\r
- * @author Nathan Sweet\r
- * @author christop widulle\r
- */\r
-public class IntHashMap<T> {\r
- public int size;\r
-\r
- Entry[] table;\r
- private float loadFactor;\r
- private int mask, capacity, threshold;\r
- private Entries entries;\r
- private Values values;\r
- private Keys keys;\r
-\r
- public IntHashMap () {\r
- this(16, 0.75f);\r
- }\r
-\r
- public IntHashMap (int initialCapacity) {\r
- this(initialCapacity, 0.75f);\r
- }\r
-\r
- public IntHashMap (int initialCapacity, float loadFactor) {\r
- if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
- if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
- if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
- capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
- this.loadFactor = loadFactor;\r
- threshold = (int)(capacity * loadFactor);\r
- table = new Entry[capacity];\r
- mask = capacity - 1;\r
- }\r
-\r
- public T put (int key, T value) {\r
- int index = key & mask;\r
- for (Entry e = table[index]; e != null; e = e.next) {\r
- if (e.key != key) continue;\r
- // Key already exists.\r
- Object oldValue = e.value;\r
- e.value = value;\r
- return (T)oldValue;\r
- }\r
- table[index] = new Entry(key, value, table[index]);\r
- if (size++ >= threshold) resize(2 * capacity);\r
- return null;\r
- }\r
-\r
- public T get (int key) {\r
- int index = key & mask;\r
- for (Entry e = table[index]; e != null; e = e.next)\r
- if (e.key == key) return (T)e.value;\r
- return null;\r
- }\r
-\r
- /**\r
- * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
- * time this method is called.\r
- */\r
- public IterableIterator<Entry<T>> entries () {\r
- if (entries == null)\r
- entries = new Entries();\r
- else\r
- entries.reset();\r
- return entries;\r
- }\r
-\r
- /**\r
- * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
- * this method is called.\r
- */\r
- public IterableIterator<T> values () {\r
- if (values == null)\r
- values = new Values();\r
- else\r
- values.reset();\r
- return values;\r
- }\r
-\r
- /**\r
- * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
- * this method is called.\r
- */\r
- public Keys keys () {\r
- if (keys == null)\r
- keys = new Keys();\r
- else\r
- keys.reset();\r
- return keys;\r
- }\r
-\r
- /**\r
- * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
- * an expensive operation.\r
- */\r
- public boolean containsValue (Object value, boolean identity) {\r
- Entry[] table = this.table;\r
- if (identity || value == null) {\r
- for (int i = table.length; i-- > 0;)\r
- for (Entry e = table[i]; e != null; e = e.next)\r
- if (e.value == value) return true;\r
- } else {\r
- for (int i = table.length; i-- > 0;)\r
- for (Entry e = table[i]; e != null; e = e.next)\r
- if (value.equals(e.value)) return true;\r
- }\r
- return false;\r
- }\r
-\r
- public boolean containsKey (int key) {\r
- int index = key & mask;\r
- for (Entry e = table[index]; e != null; e = e.next)\r
- if (e.key == key) return true;\r
- return false;\r
- }\r
-\r
- public T remove (int key) {\r
- int index = key & mask;\r
- Entry prev = table[index];\r
- Entry e = prev;\r
- while (e != null) {\r
- Entry next = e.next;\r
- if (e.key == key) {\r
- size--;\r
- if (prev == e)\r
- table[index] = next;\r
- else\r
- prev.next = next;\r
- return (T)e.value;\r
- }\r
- prev = e;\r
- e = next;\r
- }\r
- return null;\r
- }\r
-\r
- public void clear () {\r
- Entry[] table = this.table;\r
- for (int index = table.length; --index >= 0;)\r
- table[index] = null;\r
- size = 0;\r
- }\r
-\r
- /**\r
- * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
- * items to avoid multiple backing array resizes.\r
- */\r
- public void ensureCapacity (int additionalCapacity) {\r
- int sizeNeeded = size + additionalCapacity;\r
- if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
- }\r
-\r
- private void resize (int newSize) {\r
- Entry[] newTable = new Entry[newSize];\r
- Entry[] table = this.table;\r
- int bucketmask = newSize - 1;\r
- for (int i = 0; i < table.length; i++) {\r
- Entry entry = table[i];\r
- if (entry != null) {\r
- table[i] = null;\r
- do {\r
- Entry next = entry.next;\r
- int index = entry.key & bucketmask;\r
- entry.next = newTable[index];\r
- newTable[index] = entry;\r
- entry = next;\r
- } while (entry != null);\r
- }\r
- }\r
- this.table = newTable;\r
- capacity = newSize;\r
- threshold = (int)(newSize * loadFactor);\r
- mask = capacity - 1;\r
- }\r
-\r
- public String toString () {\r
- if (size == 0) return "[]";\r
- StringBuilder buffer = new StringBuilder(32);\r
- buffer.append('[');\r
- Entry[] table = this.table;\r
- int i = table.length;\r
- while (i-- > 0) {\r
- Entry e = table[i];\r
- if (e == null) continue;\r
- buffer.append(e.key);\r
- buffer.append('=');\r
- buffer.append(e.value);\r
- for (e = e.next; e != null; e = e.next) {\r
- buffer.append(", ");\r
- buffer.append(e.key);\r
- buffer.append('=');\r
- buffer.append(e.value);\r
- }\r
- break;\r
- }\r
- while (i-- > 0) {\r
- for (Entry e = table[i]; e != null; e = e.next) {\r
- buffer.append(", ");\r
- buffer.append(e.key);\r
- buffer.append('=');\r
- buffer.append(e.value);\r
- }\r
- }\r
- buffer.append(']');\r
- return buffer.toString();\r
- }\r
-\r
- class Entries implements IterableIterator {\r
- private int index = -1;\r
- Entry<T> entry = null;\r
-\r
- public boolean hasNext () {\r
- if (entry != null && entry.next != null) {\r
- entry = entry.next;\r
- return true;\r
- }\r
- while (true) {\r
- index++;\r
- if (index >= table.length) return false;\r
- if (table[index] == null) continue;\r
- entry = table[index];\r
- return true;\r
- }\r
- }\r
-\r
- public Object next () {\r
- return entry;\r
- }\r
-\r
- public void remove () {\r
- Entry prev = table[index];\r
- Entry e = prev;\r
- while (e != null) {\r
- Entry next = e.next;\r
- if (e == entry) {\r
- size--;\r
- if (prev == e)\r
- table[index] = next;\r
- else\r
- prev.next = next;\r
- return;\r
- }\r
- prev = e;\r
- e = next;\r
- }\r
- }\r
-\r
- void reset () {\r
- index = -1;\r
- entry = null;\r
- }\r
-\r
- public Iterator iterator () {\r
- return this;\r
- }\r
- }\r
-\r
- class Values extends Entries {\r
- public T next () {\r
- return entry.value;\r
- }\r
- }\r
-\r
- public class Keys {\r
- private int index = -1;\r
- Entry<T> entry = null;\r
-\r
- public boolean hasNext () {\r
- if (entry != null && entry.next != null) {\r
- entry = entry.next;\r
- return true;\r
- }\r
- while (true) {\r
- index++;\r
- if (index >= table.length) return false;\r
- if (table[index] == null) continue;\r
- entry = table[index];\r
- return true;\r
- }\r
- }\r
-\r
- public int next () {\r
- return entry.key;\r
- }\r
-\r
- public void remove () {\r
- Entry prev = table[index];\r
- Entry e = prev;\r
- while (e != null) {\r
- Entry next = e.next;\r
- if (e == entry) {\r
- size--;\r
- if (prev == e)\r
- table[index] = next;\r
- else\r
- prev.next = next;\r
- return;\r
- }\r
- prev = e;\r
- e = next;\r
- }\r
- }\r
-\r
- void reset () {\r
- index = -1;\r
- entry = null;\r
- }\r
- }\r
-\r
- /**\r
- * An entry in the map. The value may be changed directly.\r
- */\r
- static public class Entry<T> {\r
- public final int key;\r
- public T value;\r
- Entry next;\r
-\r
- Entry (int k, T v, Entry n) {\r
- key = k;\r
- value = v;\r
- next = n;\r
- }\r
-\r
- public String toString () {\r
- return key + "=" + value;\r
- }\r
- }\r
-}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Iterator;\r
+\r
+import com.badlogic.gdx.utils.ObjectMap.Entry;\r
+\r
+/**\r
+ * An unordered map that uses int keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put. This class also avoids the boxing that occurs with\r
+ * HashMap<Integer, T>.<br>\r
+ * <br>\r
+ * Warning: Integer.MIN_VALUE cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class IntMap<V> {\r
+ static private final int EXTRA = 4;\r
+ static private final int EMPTY = Integer.MIN_VALUE;\r
+\r
+ public int size;\r
+\r
+ int[] keyTable;\r
+ V[] valueTable;\r
+ private float loadFactor;\r
+ private int mask, capacity, threshold;\r
+ private Entries entries;\r
+ private Values values;\r
+ private Keys keys;\r
+\r
+ public IntMap () {\r
+ this(16, 0.75f);\r
+ }\r
+\r
+ public IntMap (int initialCapacity) {\r
+ this(initialCapacity, 0.75f);\r
+ }\r
+\r
+ public IntMap (int initialCapacity, float loadFactor) {\r
+ if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+ if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+ this.loadFactor = loadFactor;\r
+ threshold = (int)(capacity * loadFactor);\r
+ keyTable = new int[capacity + EXTRA];\r
+ for (int i = keyTable.length - 1; i >= 0; i--)\r
+ keyTable[i] = EMPTY;\r
+ valueTable = (V[])new Object[capacity + EXTRA];\r
+ mask = capacity - 1;\r
+ }\r
+\r
+ public V put (int key, V value) {\r
+ int[] keyTable = this.keyTable;\r
+ int index = key & mask;\r
+ while (true) {\r
+ int existingKey = keyTable[index];\r
+ if (existingKey == EMPTY || existingKey == key) break;\r
+ index++;\r
+ }\r
+ keyTable[index] = key;\r
+ V oldValue = valueTable[index];\r
+ valueTable[index] = value;\r
+ if (size++ >= threshold || keyTable[keyTable.length - 1] != EMPTY) resize(capacity << 1);\r
+ return oldValue;\r
+ }\r
+\r
+ public void putAll (IntMap<V> map) {\r
+ ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+ for (Entry<V> entry : map.entries())\r
+ put(entry.key, entry.value);\r
+ }\r
+\r
+ public V get (int key) {\r
+ int[] keyTable = this.keyTable;\r
+ int index = key & mask;\r
+ while (true) {\r
+ int existingKey = keyTable[index];\r
+ if (existingKey == EMPTY) return null;\r
+ if (existingKey == key) return valueTable[index];\r
+ index++;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+ * an expensive operation.\r
+ */\r
+ public boolean containsValue (Object value, boolean identity) {\r
+ V[] valueTable = this.valueTable;\r
+ if (value == null) {\r
+ int[] keyTable = this.keyTable;\r
+ for (int i = keyTable.length; i-- > 0;)\r
+ if (keyTable[i] != EMPTY && valueTable[i] == null) return true;\r
+ } else if (identity) {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (valueTable[i] == value) return true;\r
+ } else {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (value.equals(valueTable[i])) return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean containsKey (int key) {\r
+ int[] keyTable = this.keyTable;\r
+ int index = key & mask;\r
+ while (true) {\r
+ int existingKey = keyTable[index];\r
+ if (existingKey == EMPTY) return false;\r
+ if (existingKey == key) return true;\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public V remove (int key) {\r
+ int[] keyTable = this.keyTable;\r
+ int index = key & mask;\r
+ while (true) {\r
+ int existingKey = keyTable[index];\r
+ if (existingKey == EMPTY) return null;\r
+ if (existingKey == key) {\r
+ keyTable[index] = EMPTY;\r
+ V value = valueTable[index];\r
+ valueTable[index] = null;\r
+ return value;\r
+ }\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public void clear () {\r
+ int[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = keyTable.length; i-- > 0;) {\r
+ if (keyTable[i] != EMPTY) {\r
+ keyTable[i] = EMPTY;\r
+ valueTable[i] = null;\r
+ }\r
+ }\r
+ size = 0;\r
+ }\r
+\r
+ /**\r
+ * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+ * items to avoid multiple backing array resizes.\r
+ */\r
+ public void ensureCapacity (int additionalCapacity) {\r
+ int sizeNeeded = size + additionalCapacity;\r
+ if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+ }\r
+\r
+ private void resize (int newSize) {\r
+ int newMask = newSize - 1;\r
+ mask = newMask;\r
+ capacity = newSize;\r
+ threshold = (int)(newSize * loadFactor);\r
+\r
+ newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+ int[] newKeyTable = new int[newSize];\r
+ for (int i = newSize - 1; i >= 0; i--)\r
+ newKeyTable[i] = EMPTY;\r
+ V[] newValueTable = (V[])new Object[newSize];\r
+\r
+ int[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = 0, n = keyTable.length; i < n; i++) {\r
+ int key = keyTable[i];\r
+ if (key != EMPTY) {\r
+ int index = key & newMask;\r
+ while (true) {\r
+ if (newKeyTable[index] == EMPTY) break;\r
+ index++;\r
+ }\r
+ if (index == newSize) {\r
+ // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+ resize(capacity << 1);\r
+ return;\r
+ }\r
+ newKeyTable[index] = key;\r
+ newValueTable[index] = valueTable[i];\r
+ }\r
+ }\r
+ this.keyTable = newKeyTable;\r
+ this.valueTable = newValueTable;\r
+ }\r
+\r
+ public String toString () {\r
+ if (size == 0) return "[]";\r
+ StringBuilder buffer = new StringBuilder(32);\r
+ buffer.append('[');\r
+\r
+ int[] keyTable = this.keyTable;\r
+ int i = keyTable.length;\r
+ while (i-- > 0) {\r
+ int key = keyTable[i];\r
+ if (key == EMPTY) continue;\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ break;\r
+ }\r
+ while (i-- > 0) {\r
+ int key = keyTable[i];\r
+ if (key == EMPTY) continue;\r
+ buffer.append(", ");\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ }\r
+ buffer.append(']');\r
+ return buffer.toString();\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+ * time this method is called.\r
+ */\r
+ public Entries<V> entries () {\r
+ if (entries == null)\r
+ entries = new Entries(this);\r
+ else\r
+ entries.reset();\r
+ return entries;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Values<V> values () {\r
+ if (values == null)\r
+ values = new Values(this);\r
+ else\r
+ values.reset();\r
+ return values;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Keys keys () {\r
+ if (keys == null)\r
+ keys = new Keys(this);\r
+ else\r
+ keys.reset();\r
+ return keys;\r
+ }\r
+\r
+ static public class Entry<V> {\r
+ public int key;\r
+ public V value;\r
+\r
+ public String toString () {\r
+ return key + "=" + value;\r
+ }\r
+ }\r
+\r
+ static public class Entries<V> implements Iterable<Entry<V>>, Iterator<Entry<V>> {\r
+ Entry<V> entry = new Entry();\r
+ int index = -1;\r
+ private final IntMap map;\r
+\r
+ public Entries (IntMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ int[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != EMPTY) return true;\r
+ return false;\r
+ }\r
+\r
+ public Entry<V> next () {\r
+ entry.key = map.keyTable[index];\r
+ entry.value = (V)map.valueTable[index];\r
+ return entry;\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = EMPTY;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<Entry<V>> iterator () {\r
+ return this;\r
+ }\r
+ }\r
+\r
+ static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+ int index = -1;\r
+ private final IntMap map;\r
+\r
+ public Values (IntMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ int[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != EMPTY) return true;\r
+ return false;\r
+ }\r
+\r
+ public V next () {\r
+ return (V)map.valueTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = EMPTY;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<V> iterator () {\r
+ return this;\r
+ }\r
+\r
+ public Array<V> toArray () {\r
+ Array array = new Array(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+\r
+ static public class Keys {\r
+ int index = -1;\r
+ private final IntMap map;\r
+\r
+ public Keys (IntMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ int[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != EMPTY) return true;\r
+ return false;\r
+ }\r
+\r
+ public int next () {\r
+ return map.keyTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = EMPTY;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public IntArray toArray () {\r
+ IntArray array = new IntArray(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-\r
-/**\r
- * A specialized lockless thread queue class template for doing single direction message passing from one thread to another.\r
- * \r
- * This queue class does NOT use the Synchronized method. However it is designed with atomic queue passing which makes it very\r
- * nice for non blocking event passing.\r
- * \r
- * This queue class keeps a fixed sized queue buffer which must be defined during initialization. If the queue buffer gets filled\r
- * up, any new queue request will get dropped.\r
- * \r
- * This queue class also handles object pooling such that no extra allocation will be used. This prevents bad GC trashing.\r
- */\r
-public class LocklessThreadQueue<T> {\r
- /**\r
- * Interface for an Object Factory for the initial buffer creation.\r
- * @param <T> the type\r
- */\r
- public interface ObjectFactory<T> {\r
- public T createObject ();\r
- }\r
-\r
- protected List<T> queueBuffer;\r
- protected AtomicInteger head;\r
- protected AtomicInteger tail;\r
- protected int queueSize;\r
-\r
- /**\r
- * Constructor.\r
- * @param factory Object factory for pre-buffered queue pool allocation.\r
- * @param size Number of queue objects allowed before dropping queue request.\r
- */\r
- public LocklessThreadQueue (ObjectFactory<T> factory, int size) {\r
- queueSize = size + 2;\r
- queueBuffer = new ArrayList<T>(queueSize);\r
- head = new AtomicInteger(0);\r
- tail = new AtomicInteger(size + 1);\r
-\r
- for (int i = 0; i < queueSize; ++i) {\r
- queueBuffer.add(factory.createObject());\r
- }\r
- }\r
-\r
- /** Returns the next available preallocated object for preparation. */\r
- public T prepare () {\r
- int currHead = head.get();\r
- int nextHead = (currHead + 1) % queueSize;\r
- if (nextHead == tail.get()) return null;\r
- return queueBuffer.get(currHead);\r
- }\r
-\r
- /**\r
- * Push the next available object to the queue. This must be called after prepare is called for preparation. If it prepare()\r
- * was not called, this will simply push the object unchanged from it's last queued state.\r
- */\r
- public void push () {\r
- int nextHead = (head.get() + 1) % queueSize;\r
- if (nextHead == tail.get()) return;\r
- head.set(nextHead);\r
- }\r
-\r
- /** Returns null or the next queued object in the queue list */\r
- public T pop () {\r
- int nextTail = (tail.get() + 1) % queueSize;\r
- if (head.get() == nextTail) return null;\r
- T object = queueBuffer.get(nextTail);\r
- tail.set(nextTail);\r
- return object;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.Iterator;\r
-\r
-/**\r
- * An unordered map that uses long keys. Avoids the boxing that occurs with HashMap<Long, T>.\r
- * @author Nathan Sweet\r
- * @author christop widulle\r
- */\r
-public class LongHashMap<T> {\r
- public int size;\r
-\r
- Entry[] table;\r
- private float loadFactor;\r
- private int mask, capacity, threshold;\r
- private Entries entries;\r
- private Values values;\r
- private Keys keys;\r
-\r
- public LongHashMap () {\r
- this(16, 0.75f);\r
- }\r
-\r
- public LongHashMap (int initialCapacity) {\r
- this(initialCapacity, 0.75f);\r
- }\r
-\r
- public LongHashMap (int initialCapacity, float loadFactor) {\r
- if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
- if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
- if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
- capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
- this.loadFactor = loadFactor;\r
- threshold = (int)(capacity * loadFactor);\r
- table = new Entry[capacity];\r
- mask = capacity - 1;\r
- }\r
-\r
- public T put (long key, T value) {\r
- int index = (int)(key & mask);\r
- for (Entry e = table[index]; e != null; e = e.next) {\r
- if (e.key != key) continue;\r
- // Key already exists.\r
- Object oldValue = e.value;\r
- e.value = value;\r
- return (T)oldValue;\r
- }\r
- table[index] = new Entry(key, value, table[index]);\r
- if (size++ >= threshold) resize(2 * capacity);\r
- return null;\r
- }\r
-\r
- public T get (long key) {\r
- int index = (int)(key & mask);\r
- for (Entry e = table[index]; e != null; e = e.next)\r
- if (e.key == key) return (T)e.value;\r
- return null;\r
- }\r
-\r
- /**\r
- * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
- * time this method is called.\r
- */\r
- public Iterator entries () {\r
- if (entries == null)\r
- entries = new Entries();\r
- else\r
- entries.reset();\r
- return entries;\r
- }\r
-\r
- /**\r
- * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
- * this method is called.\r
- */\r
- public Iterator values () {\r
- if (values == null)\r
- values = new Values();\r
- else\r
- values.reset();\r
- return values;\r
- }\r
-\r
- /**\r
- * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
- * this method is called.\r
- */\r
- public Keys keys () {\r
- if (keys == null)\r
- keys = new Keys();\r
- else\r
- keys.reset();\r
- return keys;\r
- }\r
-\r
- /**\r
- * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
- * an expensive operation.\r
- */\r
- public boolean containsValue (Object value, boolean identity) {\r
- Entry[] table = this.table;\r
- if (identity || value == null) {\r
- for (int i = table.length; i-- > 0;)\r
- for (Entry e = table[i]; e != null; e = e.next)\r
- if (e.value == value) return true;\r
- } else {\r
- for (int i = table.length; i-- > 0;)\r
- for (Entry e = table[i]; e != null; e = e.next)\r
- if (value.equals(e.value)) return true;\r
- }\r
- return false;\r
- }\r
-\r
- public boolean containsKey (long key) {\r
- int index = (int)(key & mask);\r
- for (Entry e = table[index]; e != null; e = e.next)\r
- if (e.key == key) return true;\r
- return false;\r
- }\r
-\r
- public T remove (long key) {\r
- int index = (int)(key & mask);\r
- Entry prev = table[index];\r
- Entry e = prev;\r
- while (e != null) {\r
- Entry next = e.next;\r
- if (e.key == key) {\r
- size--;\r
- if (prev == e)\r
- table[index] = next;\r
- else\r
- prev.next = next;\r
- return (T)e.value;\r
- }\r
- prev = e;\r
- e = next;\r
- }\r
- return null;\r
- }\r
-\r
- public void clear () {\r
- Entry[] table = this.table;\r
- for (int index = table.length; --index >= 0;)\r
- table[index] = null;\r
- size = 0;\r
- }\r
-\r
- /**\r
- * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
- * items to avoid multiple backing array resizes.\r
- */\r
- public void ensureCapacity (int additionalCapacity) {\r
- int sizeNeeded = size + additionalCapacity;\r
- if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
- }\r
-\r
- private void resize (int newSize) {\r
- Entry[] newTable = new Entry[newSize];\r
- Entry[] table = this.table;\r
- int bucketmask = newSize - 1;\r
- for (int i = 0; i < table.length; i++) {\r
- Entry entry = table[i];\r
- if (entry != null) {\r
- table[i] = null;\r
- do {\r
- Entry next = entry.next;\r
- int index = (int)(entry.key & bucketmask);\r
- entry.next = newTable[index];\r
- newTable[index] = entry;\r
- entry = next;\r
- } while (entry != null);\r
- }\r
- }\r
- this.table = newTable;\r
- capacity = newSize;\r
- threshold = (int)(newSize * loadFactor);\r
- mask = capacity - 1;\r
- }\r
-\r
- public String toString () {\r
- if (size == 0) return "[]";\r
- StringBuilder buffer = new StringBuilder(32);\r
- buffer.append('[');\r
- Entry[] table = this.table;\r
- int i = table.length;\r
- while (i-- > 0) {\r
- Entry e = table[i];\r
- if (e == null) continue;\r
- buffer.append(e.key);\r
- buffer.append('=');\r
- buffer.append(e.value);\r
- for (e = e.next; e != null; e = e.next) {\r
- buffer.append(", ");\r
- buffer.append(e.key);\r
- buffer.append('=');\r
- buffer.append(e.value);\r
- }\r
- break;\r
- }\r
- while (i-- > 0) {\r
- for (Entry e = table[i]; e != null; e = e.next) {\r
- buffer.append(", ");\r
- buffer.append(e.key);\r
- buffer.append('=');\r
- buffer.append(e.value);\r
- }\r
- }\r
- buffer.append(']');\r
- return buffer.toString();\r
- }\r
-\r
- class Entries implements Iterator {\r
- private int index = -1;\r
- Entry<T> entry = null;\r
-\r
- public boolean hasNext () {\r
- if (entry != null && entry.next != null) {\r
- entry = entry.next;\r
- return true;\r
- }\r
- while (true) {\r
- index++;\r
- if (index >= table.length) return false;\r
- if (table[index] == null) continue;\r
- entry = table[index];\r
- return true;\r
- }\r
- }\r
-\r
- public Object next () {\r
- return entry;\r
- }\r
-\r
- public void remove () {\r
- Entry prev = table[index];\r
- Entry e = prev;\r
- while (e != null) {\r
- Entry next = e.next;\r
- if (e == entry) {\r
- size--;\r
- if (prev == e)\r
- table[index] = next;\r
- else\r
- prev.next = next;\r
- return;\r
- }\r
- prev = e;\r
- e = next;\r
- }\r
- }\r
-\r
- void reset () {\r
- index = -1;\r
- entry = null;\r
- }\r
- }\r
-\r
- class Values extends Entries {\r
- public T next () {\r
- return entry.value;\r
- }\r
- }\r
-\r
- class Keys {\r
- private int index = -1;\r
- Entry<T> entry = null;\r
-\r
- public boolean hasNext () {\r
- if (entry != null && entry.next != null) {\r
- entry = entry.next;\r
- return true;\r
- }\r
- while (true) {\r
- index++;\r
- if (index >= table.length) return false;\r
- if (table[index] == null) continue;\r
- entry = table[index];\r
- return true;\r
- }\r
- }\r
-\r
- public long next () {\r
- return entry.key;\r
- }\r
-\r
- public void remove () {\r
- Entry prev = table[index];\r
- Entry e = prev;\r
- while (e != null) {\r
- Entry next = e.next;\r
- if (e == entry) {\r
- size--;\r
- if (prev == e)\r
- table[index] = next;\r
- else\r
- prev.next = next;\r
- return;\r
- }\r
- prev = e;\r
- e = next;\r
- }\r
- }\r
-\r
- void reset () {\r
- index = -1;\r
- entry = null;\r
- }\r
- }\r
-\r
- /**\r
- * An entry in the map. The value may be changed directly.\r
- */\r
- static public class Entry<T> {\r
- public final long key;\r
- public T value;\r
- Entry next;\r
-\r
- Entry (long k, T v, Entry n) {\r
- key = k;\r
- value = v;\r
- next = n;\r
- }\r
-\r
- public String toString () {\r
- return key + "=" + value;\r
- }\r
- }\r
-}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+\r
+import com.badlogic.gdx.utils.ObjectMap.Entry;\r
+\r
+/**\r
+ * An unordered map that uses long keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put. This class also avoids the boxing that occurs with HashMap<Long,\r
+ * T>.<br>\r
+ * <br>\r
+ * Warning: Integer.MIN_VALUE cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class LongMap<V> {\r
+ static private final int EXTRA = 4;\r
+ static private final int EMPTY = Integer.MIN_VALUE;\r
+\r
+ public int size;\r
+\r
+ long[] keyTable;\r
+ V[] valueTable;\r
+ private float loadFactor;\r
+ private int mask, capacity, threshold;\r
+ private Entries entries;\r
+ private Values values;\r
+ private Keys keys;\r
+\r
+ public LongMap () {\r
+ this(16, 0.75f);\r
+ }\r
+\r
+ public LongMap (int initialCapacity) {\r
+ this(initialCapacity, 0.75f);\r
+ }\r
+\r
+ public LongMap (int initialCapacity, float loadFactor) {\r
+ if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+ if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+ this.loadFactor = loadFactor;\r
+ threshold = (int)(capacity * loadFactor);\r
+ keyTable = new long[capacity + EXTRA];\r
+ for (int i = keyTable.length - 1; i >= 0; i--)\r
+ keyTable[i] = EMPTY;\r
+ valueTable = (V[])new Object[capacity + EXTRA];\r
+ mask = capacity - 1;\r
+ }\r
+\r
+ public V put (long key, V value) {\r
+ long[] keyTable = this.keyTable;\r
+ int index = (int)(key & mask);\r
+ while (true) {\r
+ long existingKey = keyTable[index];\r
+ if (existingKey == EMPTY || existingKey == key) break;\r
+ index++;\r
+ }\r
+ keyTable[index] = key;\r
+ V oldValue = valueTable[index];\r
+ valueTable[index] = value;\r
+ if (size++ >= threshold || keyTable[keyTable.length - 1] != EMPTY) resize(capacity << 1);\r
+ return oldValue;\r
+ }\r
+\r
+ public void putAll (LongMap<V> map) {\r
+ ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+ for (Entry<V> entry : map.entries())\r
+ put(entry.key, entry.value);\r
+ }\r
+\r
+ public V get (long key) {\r
+ long[] keyTable = this.keyTable;\r
+ int index = (int)(key & mask);\r
+ while (true) {\r
+ long existingKey = keyTable[index];\r
+ if (existingKey == EMPTY) return null;\r
+ if (existingKey == key) return valueTable[index];\r
+ index++;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+ * an expensive operation.\r
+ */\r
+ public boolean containsValue (Object value, boolean identity) {\r
+ V[] valueTable = this.valueTable;\r
+ if (value == null) {\r
+ long[] keyTable = this.keyTable;\r
+ for (int i = keyTable.length; i-- > 0;)\r
+ if (keyTable[i] != EMPTY && valueTable[i] == null) return true;\r
+ } else if (identity) {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (valueTable[i] == value) return true;\r
+ } else {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (value.equals(valueTable[i])) return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean containsKey (long key) {\r
+ long[] keyTable = this.keyTable;\r
+ int index = (int)(key & mask);\r
+ while (true) {\r
+ long existingKey = keyTable[index];\r
+ if (existingKey == EMPTY) return false;\r
+ if (existingKey == key) return true;\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public V remove (long key) {\r
+ long[] keyTable = this.keyTable;\r
+ int index = (int)(key & mask);\r
+ while (true) {\r
+ long existingKey = keyTable[index];\r
+ if (existingKey == EMPTY) return null;\r
+ if (existingKey == key) {\r
+ keyTable[index] = EMPTY;\r
+ V value = valueTable[index];\r
+ valueTable[index] = null;\r
+ return value;\r
+ }\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public void clear () {\r
+ long[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = keyTable.length; i-- > 0;) {\r
+ if (keyTable[i] != EMPTY) {\r
+ keyTable[i] = EMPTY;\r
+ valueTable[i] = null;\r
+ }\r
+ }\r
+ size = 0;\r
+ }\r
+\r
+ /**\r
+ * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+ * items to avoid multiple backing array resizes.\r
+ */\r
+ public void ensureCapacity (int additionalCapacity) {\r
+ int sizeNeeded = size + additionalCapacity;\r
+ if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+ }\r
+\r
+ private void resize (int newSize) {\r
+ int newMask = newSize - 1;\r
+ mask = newMask;\r
+ capacity = newSize;\r
+ threshold = (int)(newSize * loadFactor);\r
+\r
+ newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+ long[] newKeyTable = new long[newSize];\r
+ for (int i = newSize - 1; i >= 0; i--)\r
+ newKeyTable[i] = EMPTY;\r
+ V[] newValueTable = (V[])new Object[newSize];\r
+\r
+ long[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = 0, n = keyTable.length; i < n; i++) {\r
+ long key = keyTable[i];\r
+ if (key != EMPTY) {\r
+ int index = (int)(key & newMask);\r
+ while (true) {\r
+ if (newKeyTable[index] == EMPTY) break;\r
+ index++;\r
+ }\r
+ if (index == newSize) {\r
+ // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+ resize(capacity << 1);\r
+ return;\r
+ }\r
+ newKeyTable[index] = key;\r
+ newValueTable[index] = valueTable[i];\r
+ }\r
+ }\r
+ this.keyTable = newKeyTable;\r
+ this.valueTable = newValueTable;\r
+ }\r
+\r
+ public String toString () {\r
+ if (size == 0) return "[]";\r
+ StringBuilder buffer = new StringBuilder(32);\r
+ buffer.append('[');\r
+\r
+ long[] keyTable = this.keyTable;\r
+ int i = keyTable.length;\r
+ while (i-- > 0) {\r
+ long key = keyTable[i];\r
+ if (key == EMPTY) continue;\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ break;\r
+ }\r
+ while (i-- > 0) {\r
+ long key = keyTable[i];\r
+ if (key == EMPTY) continue;\r
+ buffer.append(", ");\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ }\r
+ buffer.append(']');\r
+ return buffer.toString();\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+ * time this method is called.\r
+ */\r
+ public Entries<V> entries () {\r
+ if (entries == null)\r
+ entries = new Entries(this);\r
+ else\r
+ entries.reset();\r
+ return entries;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Values<V> values () {\r
+ if (values == null)\r
+ values = new Values(this);\r
+ else\r
+ values.reset();\r
+ return values;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Keys keys () {\r
+ if (keys == null)\r
+ keys = new Keys(this);\r
+ else\r
+ keys.reset();\r
+ return keys;\r
+ }\r
+\r
+ static public class Entry<V> {\r
+ public long key;\r
+ public V value;\r
+\r
+ public String toString () {\r
+ return key + "=" + value;\r
+ }\r
+ }\r
+\r
+ static public class Entries<V> implements Iterable<Entry<V>>, Iterator<Entry<V>> {\r
+ Entry<V> entry = new Entry();\r
+ int index = -1;\r
+ private final LongMap map;\r
+\r
+ public Entries (LongMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ long[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != EMPTY) return true;\r
+ return false;\r
+ }\r
+\r
+ public Entry<V> next () {\r
+ entry.key = map.keyTable[index];\r
+ entry.value = (V)map.valueTable[index];\r
+ return entry;\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = EMPTY;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<Entry<V>> iterator () {\r
+ return this;\r
+ }\r
+ }\r
+\r
+ static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+ int index = -1;\r
+ private final LongMap map;\r
+\r
+ public Values (LongMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ long[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != EMPTY) return true;\r
+ return false;\r
+ }\r
+\r
+ public V next () {\r
+ return (V)map.valueTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = EMPTY;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<V> iterator () {\r
+ return this;\r
+ }\r
+\r
+ public Array<V> toArray () {\r
+ Array array = new Array(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+\r
+ static public class Keys {\r
+ int index = -1;\r
+ private final LongMap map;\r
+\r
+ public Keys (LongMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ long[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != EMPTY) return true;\r
+ return false;\r
+ }\r
+\r
+ public long next () {\r
+ return map.keyTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = EMPTY;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public LongArray toArray () {\r
+ LongArray array = new LongArray(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Iterator;\r
+\r
+/**\r
+ * An unordered map that uses int keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put.<br>\r
+ * <br>\r
+ * Warning: null cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class ObjectMap<K, V> {\r
+ static private final int EXTRA = 4;\r
+\r
+ public int size;\r
+\r
+ K[] keyTable;\r
+ V[] valueTable;\r
+ private float loadFactor;\r
+ private int mask, capacity, threshold;\r
+ private Entries entries;\r
+ private Values values;\r
+ private Keys keys;\r
+\r
+ public ObjectMap () {\r
+ this(16, 0.75f);\r
+ }\r
+\r
+ public ObjectMap (int initialCapacity) {\r
+ this(initialCapacity, 0.75f);\r
+ }\r
+\r
+ public ObjectMap (int initialCapacity, float loadFactor) {\r
+ if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+ if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+ capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+ this.loadFactor = loadFactor;\r
+ threshold = (int)(capacity * loadFactor);\r
+ keyTable = (K[])new Object[capacity + EXTRA];\r
+ valueTable = (V[])new Object[capacity + EXTRA];\r
+ mask = capacity - 1;\r
+ }\r
+\r
+ public V put (K key, V value) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = key.hashCode() & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null || existingKey.equals(key)) break;\r
+ index++;\r
+ }\r
+ keyTable[index] = key;\r
+ V oldValue = valueTable[index];\r
+ valueTable[index] = value;\r
+ if (size++ >= threshold || keyTable[keyTable.length - 1] != null) resize(capacity << 1);\r
+ return oldValue;\r
+ }\r
+\r
+ public void putAll (ObjectMap<K, V> map) {\r
+ ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+ for (Entry<K, V> entry : map.entries())\r
+ put(entry.key, entry.value);\r
+ }\r
+\r
+ public V get (K key) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = key.hashCode() & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null) return null;\r
+ if (existingKey.equals(key)) return valueTable[index];\r
+ index++;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+ * an expensive operation.\r
+ */\r
+ public boolean containsValue (Object value, boolean identity) {\r
+ V[] valueTable = this.valueTable;\r
+ if (value == null) {\r
+ K[] keyTable = this.keyTable;\r
+ for (int i = keyTable.length; i-- > 0;)\r
+ if (keyTable[i] != null && valueTable[i] == null) return true;\r
+ } else if (identity) {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (value.equals(valueTable[i])) return true;\r
+ } else {\r
+ for (int i = valueTable.length; i-- > 0;)\r
+ if (value.equals(valueTable[i])) return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean containsKey (K key) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = key.hashCode() & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null) return false;\r
+ if (existingKey.equals(key)) return true;\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public V remove (K key) {\r
+ K[] keyTable = this.keyTable;\r
+ int index = key.hashCode() & mask;\r
+ while (true) {\r
+ K existingKey = keyTable[index];\r
+ if (existingKey == null) return null;\r
+ if (existingKey.equals(key)) {\r
+ keyTable[index] = null;\r
+ V value = valueTable[index];\r
+ valueTable[index] = null;\r
+ return value;\r
+ }\r
+ index++;\r
+ }\r
+ }\r
+\r
+ public void clear () {\r
+ K[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = keyTable.length; i-- > 0;) {\r
+ if (keyTable[i] != null) {\r
+ keyTable[i] = null;\r
+ valueTable[i] = null;\r
+ }\r
+ }\r
+ size = 0;\r
+ }\r
+\r
+ /**\r
+ * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+ * items to avoid multiple backing array resizes.\r
+ */\r
+ public void ensureCapacity (int additionalCapacity) {\r
+ int sizeNeeded = size + additionalCapacity;\r
+ if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+ }\r
+\r
+ private void resize (int newSize) {\r
+ int newMask = newSize - 1;\r
+ mask = newMask;\r
+ capacity = newSize;\r
+ threshold = (int)(newSize * loadFactor);\r
+\r
+ newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+ K[] newKeyTable = (K[])new Object[newSize];\r
+ V[] newValueTable = (V[])new Object[newSize];\r
+\r
+ K[] keyTable = this.keyTable;\r
+ V[] valueTable = this.valueTable;\r
+ for (int i = 0, n = keyTable.length; i < n; i++) {\r
+ K key = keyTable[i];\r
+ if (key != null) {\r
+ int index = key.hashCode() & newMask;\r
+ while (true) {\r
+ if (newKeyTable[index] == null) break;\r
+ index++;\r
+ }\r
+ if (index == newSize) {\r
+ // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+ resize(capacity << 1);\r
+ return;\r
+ }\r
+ newKeyTable[index] = key;\r
+ newValueTable[index] = valueTable[i];\r
+ }\r
+ }\r
+ this.keyTable = newKeyTable;\r
+ this.valueTable = newValueTable;\r
+ }\r
+\r
+ public String toString () {\r
+ if (size == 0) return "[]";\r
+ StringBuilder buffer = new StringBuilder(32);\r
+ buffer.append('[');\r
+\r
+ K[] keyTable = this.keyTable;\r
+ int i = keyTable.length;\r
+ while (i-- > 0) {\r
+ K key = keyTable[i];\r
+ if (key == null) continue;\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ break;\r
+ }\r
+ while (i-- > 0) {\r
+ K key = keyTable[i];\r
+ if (key == null) continue;\r
+ buffer.append(", ");\r
+ buffer.append(key);\r
+ buffer.append('=');\r
+ buffer.append(valueTable[i]);\r
+ }\r
+ buffer.append(']');\r
+ return buffer.toString();\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+ * time this method is called.\r
+ */\r
+ public Entries<K, V> entries () {\r
+ if (entries == null)\r
+ entries = new Entries(this);\r
+ else\r
+ entries.reset();\r
+ return entries;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Values<V> values () {\r
+ if (values == null)\r
+ values = new Values(this);\r
+ else\r
+ values.reset();\r
+ return values;\r
+ }\r
+\r
+ /**\r
+ * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+ * this method is called.\r
+ */\r
+ public Keys<K> keys () {\r
+ if (keys == null)\r
+ keys = new Keys(this);\r
+ else\r
+ keys.reset();\r
+ return keys;\r
+ }\r
+\r
+ static public class Entry<K, V> {\r
+ public K key;\r
+ public V value;\r
+\r
+ public String toString () {\r
+ return key + "=" + value;\r
+ }\r
+ }\r
+\r
+ static public class Entries<K, V> implements Iterable<Entry<K, V>>, Iterator<Entry<K, V>> {\r
+ Entry<K, V> entry = new Entry();\r
+ int index = -1;\r
+ private final ObjectMap map;\r
+\r
+ public Entries (ObjectMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ Object[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != null) return true;\r
+ return false;\r
+ }\r
+\r
+ public Entry<K, V> next () {\r
+ entry.key = (K)map.keyTable[index];\r
+ entry.value = (V)map.valueTable[index];\r
+ return entry;\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = null;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<Entry<K, V>> iterator () {\r
+ return this;\r
+ }\r
+ }\r
+\r
+ static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+ int index = -1;\r
+ private final ObjectMap map;\r
+\r
+ public Values (ObjectMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ Object[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != null) return true;\r
+ return false;\r
+ }\r
+\r
+ public V next () {\r
+ return (V)map.valueTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = null;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<V> iterator () {\r
+ return this;\r
+ }\r
+\r
+ public Array<V> toArray () {\r
+ Array array = new Array(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+\r
+ static public class Keys<K> implements Iterable<K>, Iterator<K> {\r
+ int index = -1;\r
+ private final ObjectMap map;\r
+\r
+ public Keys (ObjectMap map) {\r
+ this.map = map;\r
+ }\r
+\r
+ public boolean hasNext () {\r
+ Object[] keyTable = map.keyTable;\r
+ for (int n = keyTable.length; ++index < n;)\r
+ if (keyTable[index] != null) return true;\r
+ return false;\r
+ }\r
+\r
+ public K next () {\r
+ return (K)map.keyTable[index];\r
+ }\r
+\r
+ public void remove () {\r
+ map.keyTable[index] = null;\r
+ map.valueTable[index] = null;\r
+ map.size--;\r
+ index--;\r
+ }\r
+\r
+ public void reset () {\r
+ index = -1;\r
+ }\r
+\r
+ public Iterator<K> iterator () {\r
+ return this;\r
+ }\r
+\r
+ public Array<K> toArray () {\r
+ Array array = new Array(map.size);\r
+ while (hasNext())\r
+ array.add(next());\r
+ return array;\r
+ }\r
+ }\r
+}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-/**\r
- * A pool implementation used for object instances that should get reused instead of being collected by the garbage collector.\r
- * Note that you should not hold on to the references of objects from this Pool once they've been marked as free by calling\r
- * {@link #free(Object)}.\r
- * \r
- * @author mzechner\r
- * \r
- * @param <T> the type\r
- */\r
-@SuppressWarnings("unchecked") public class Pool<T> {\r
- /**\r
- * Interface for an Object Factory to be used with this Pool\r
- * \r
- * @author mzechner\r
- * \r
- * @param <T> the type\r
- */\r
- public interface PoolObjectFactory<T> {\r
- public T createObject ();\r
- }\r
-\r
- /** the list of free objects **/\r
- private final List<T> freeObjects = new ArrayList();\r
- /** the factory **/\r
- private final PoolObjectFactory<T> factory;\r
- /** maximum size of pool **/\r
- private final int maxSize;\r
-\r
- public Pool (PoolObjectFactory<T> factory, int maxSize) {\r
- this.factory = factory;\r
- this.maxSize = maxSize;\r
- }\r
-\r
- /**\r
- * Creates a new object either by taking it from the free object pool or by creating a new one if there are no free objects\r
- * yet.\r
- * \r
- * @return the object\r
- */\r
- public T newObject () {\r
- T object = null;\r
-\r
- if (freeObjects.size() == 0)\r
- object = factory.createObject();\r
- else\r
- object = freeObjects.remove(freeObjects.size() - 1);\r
-\r
- return object;\r
- }\r
-\r
- /**\r
- * Frees the given object and returns it to the pool.\r
- * @param object the object\r
- */\r
- public void free (T object) {\r
- if (freeObjects.size() < maxSize) freeObjects.add(object);\r
- }\r
-}\r
\r
package com.badlogic.gdx.utils;\r
\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
-\r
/**\r
* A simple linked list that pools its nodes. This is a highly specialized class used in a couple of 2D scene graph classes. I\r
* wouldn't use it if i was you :)\r
private Item<T> curr;\r
private int size = 0;\r
\r
- private final Pool<Item<T>> pool;\r
+ private final BagPool<Item<T>> pool;\r
\r
public PooledLinkedList (int maxPoolSize) {\r
- this.pool = new Pool<PooledLinkedList.Item<T>>(new PoolObjectFactory<PooledLinkedList.Item<T>>() {\r
-\r
- @Override public PooledLinkedList.Item<T> createObject () {\r
+ this.pool = new BagPool<PooledLinkedList.Item<T>>(16, maxPoolSize) {\r
+ protected Item<T> newObject () {\r
return new Item<T>();\r
}\r
- }, maxPoolSize);\r
+ };\r
}\r
\r
public void add (T object) {\r
- Item<T> item = pool.newObject();\r
+ Item<T> item = pool.add();\r
item.payload = object;\r
item.next = null;\r
item.prev = null;\r
if (curr == null) return;\r
\r
size--;\r
- pool.free(curr);\r
+ pool.removeValue(curr, true);\r
\r
Item<T> c = curr;\r
Item<T> n = curr.next;\r
--- /dev/null
+/*\r
+ * Copyright (C) 2008 The Android Open Source Project\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Comparator;\r
+\r
+/**\r
+ * Provides methods to sort arrays or objects. Sorting requires working memory and this class allows that memory to be reused to\r
+ * avoid allocation. The sorting is otherwise identical to the Arrays.sort methods (uses timsort).<br>\r
+ * <br>\r
+ * Note that sorting primitive arrays with the Arrays.sort methods does not allocate memory (unless sorting large arrays of char,\r
+ * short, or byte).\r
+ */\r
+public class Sort {\r
+ private TimSort timSort;\r
+ private ComparableTimSort comparableTimSort;\r
+\r
+ public <T extends Comparable<T>> void sort (Array<T> a) {\r
+ if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+ comparableTimSort.doSort(a.items, 0, a.size);\r
+ }\r
+\r
+ public <T extends Comparable<T>> void sort (ArrayPool<T> a) {\r
+ if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+ comparableTimSort.doSort(a.items, 0, a.size);\r
+ }\r
+\r
+ public <T extends Comparable<T>> void sort (T[] a) {\r
+ if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+ comparableTimSort.doSort(a, 0, a.length);\r
+ }\r
+\r
+ public <T extends Comparable<T>> void sort (T[] a, int fromIndex, int toIndex) {\r
+ if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+ comparableTimSort.doSort(a, fromIndex, toIndex);\r
+ }\r
+\r
+ public <T> void sort (Array<T> a, Comparator<T> c) {\r
+ if (timSort == null) timSort = new TimSort();\r
+ timSort.doSort(a.items, c, 0, a.size);\r
+ }\r
+\r
+ public <T> void sort (ArrayPool<T> a, Comparator<T> c) {\r
+ if (timSort == null) timSort = new TimSort();\r
+ timSort.doSort(a.items, c, 0, a.size);\r
+ }\r
+\r
+ public <T> void sort (T[] a, Comparator<T> c) {\r
+ if (timSort == null) timSort = new TimSort();\r
+ timSort.doSort(a, c, 0, a.length);\r
+ }\r
+\r
+ public <T> void sort (T[] a, Comparator<T> c, int fromIndex, int toIndex) {\r
+ if (timSort == null) timSort = new TimSort();\r
+ timSort.doSort(a, c, fromIndex, toIndex);\r
+ }\r
+}\r
batch = new SpriteBatch();\r
batch.setProjectionMatrix(new Matrix4().setToOrtho2D(0, 0, 855, 480));\r
atlas = new TextureAtlas(Gdx.files.internal("data/issue_pack"), Gdx.files.internal("data/"));\r
- sprite = atlas.getSprite("map");\r
+ sprite = atlas.createSprite("map");\r
font = new BitmapFont(Gdx.files.internal("data/font.fnt"), Gdx.files.internal("data/font.png"), false);\r
Gdx.gl.glClearColor(0, 1, 0, 1);\r
}\r
String[] filterNames = { "nearest", "linear", "nearest mipmap nearest", "linear mipmap nearest", "linear mipmap linear" };\r
\r
private void setTextureFilter (int filter) {\r
- atlas.getRegion("map").getTexture().bind();\r
+ atlas.findRegion("map").getTexture().bind();\r
Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, filters[filter]);\r
texture.bind();\r
Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, filters[filter]);\r
setTextureFilter(0);\r
setModeString();\r
\r
- sprite = atlas.getSprite("map");\r
+ sprite = atlas.createSprite("map");\r
sprite2 = new Sprite(texture, 0, 0, 855, 480);\r
font = new BitmapFont(Gdx.files.internal("data/font.fnt"), Gdx.files.internal("data/font.png"), false); \r
\r
\r
atlas = new TextureAtlas(Gdx.files.internal("data"));\r
\r
- badlogic = atlas.getSprite("badlogicslice");\r
+ badlogic = atlas.createSprite("badlogicslice");\r
badlogic.setPosition(50, 50);\r
\r
- badlogicSmall = atlas.getSprite("badlogicsmall");\r
+ badlogicSmall = atlas.createSprite("badlogicsmall");\r
badlogicSmall.setPosition(10, 10);\r
badlogicSmall.flip(true, true);\r
\r
- AtlasRegion region = atlas.getRegion("badlogicsmall");\r
+ AtlasRegion region = atlas.findRegion("badlogicsmall");\r
System.out.println("badlogicSmall original size: " + region.originalWidth + ", " + region.originalHeight);\r
System.out.println("badlogicSmall packed size: " + region.packedWidth + ", " + region.packedHeight);\r
\r
- star = atlas.getSprite("particle-star");\r
+ star = atlas.createSprite("particle-star");\r
star.setPosition(10, 70);\r
\r
- font = new BitmapFont(Gdx.files.internal("data/font.fnt"), atlas.getRegion("font"), false);\r
+ font = new BitmapFont(Gdx.files.internal("data/font.fnt"), atlas.findRegion("font"), false);\r
\r
Gdx.gl.glClearColor(0, 1, 0, 1);\r
}\r