001/* 002 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.compiler.common; 024 025import static com.oracle.graal.compiler.common.CollectionsFactory.Mode.*; 026 027import java.util.*; 028 029/** 030 * Factory for creating collection objects used during compilation. 031 */ 032public class CollectionsFactory { 033 034 private static final ThreadLocal<Mode> tl = new ThreadLocal<>(); 035 036 public static class ModeScope implements AutoCloseable { 037 private final Mode previousMode; 038 039 public ModeScope(Mode previousMode) { 040 this.previousMode = previousMode; 041 } 042 043 public void close() { 044 tl.set(previousMode); 045 } 046 } 047 048 /** 049 * Constants denoting what type of collections are {@link CollectionsFactory#getMode() 050 * currently} returned by the factory. 051 */ 052 public enum Mode { 053 /** 054 * Denotes standard collections such as {@link HashSet} and {@link HashMap}. 055 */ 056 STANDARD, 057 058 /** 059 * Denotes collections that have a deterministic iteration order over their keys/entries. 060 */ 061 DETERMINISTIC_ITERATION_ORDER; 062 } 063 064 /** 065 * Gets the current mode determining the type of collection objects created by this factory. 066 */ 067 public static Mode getMode() { 068 Mode mode = tl.get(); 069 return mode == null ? Mode.STANDARD : mode; 070 } 071 072 /** 073 * Updates the mode for the current thread. 074 * 075 * @return an object which when {@linkplain ModeScope#close() closed} will revert the mode of 076 * the current thread to the state before calling this method 077 */ 078 public static ModeScope changeMode(Mode mode) { 079 Mode previousMode = tl.get(); 080 tl.set(mode); 081 return new ModeScope(previousMode); 082 } 083 084 public static <K, V> HashMap<K, V> newMap() { 085 return getMode() == STANDARD ? new HashMap<>() : new LinkedHashMap<>(); 086 } 087 088 public static <K, V> HashMap<K, V> newMap(Map<K, V> m) { 089 return getMode() == STANDARD ? new HashMap<>(m) : new LinkedHashMap<>(m); 090 } 091 092 public static <K, V> HashMap<K, V> newMap(int initialCapacity) { 093 return getMode() == STANDARD ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity); 094 } 095 096 public static <K, V> Map<K, V> newIdentityMap() { 097 return getMode() == STANDARD ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>(); 098 } 099 100 public static <K, V> Map<K, V> newIdentityMap(int expectedMaxSize) { 101 return getMode() == STANDARD ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>(); 102 } 103 104 public static <K, V> Map<K, V> newIdentityMap(Map<K, V> m) { 105 return getMode() == STANDARD ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m); 106 } 107 108 /** 109 * Creates a set. If the current thread is {@linkplain CollectionsFactory#getMode() using} 110 * {@link Mode#DETERMINISTIC_ITERATION_ORDER} collections, the returned set will have an 111 * iteration order determined by the order in which elements are inserted in the set. 112 */ 113 public static <E> Set<E> newSet() { 114 return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>() : new LinkedHashSet<>(); 115 } 116 117 /** 118 * @see #newSet() 119 */ 120 public static <E> Set<E> newSet(Collection<? extends E> c) { 121 return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>(c) : new LinkedHashSet<>(c); 122 } 123 124}