1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.core.common;
  24 
  25 import static org.graalvm.compiler.core.common.CollectionsFactory.Mode.STANDARD;
  26 
  27 import java.util.Collection;
  28 import java.util.HashMap;
  29 import java.util.HashSet;
  30 import java.util.IdentityHashMap;
  31 import java.util.LinkedHashMap;
  32 import java.util.LinkedHashSet;
  33 import java.util.Map;
  34 import java.util.Set;
  35 
  36 /**
  37  * Factory for creating collection objects used during compilation.
  38  */
  39 public class CollectionsFactory {
  40 
  41     private static final ThreadLocal<Mode> tl = new ThreadLocal<>();
  42 
  43     public static class ModeScope implements AutoCloseable {
  44         private final Mode previousMode;
  45 
  46         public ModeScope(Mode previousMode) {
  47             this.previousMode = previousMode;
  48         }
  49 
  50         @Override
  51         public void close() {
  52             tl.set(previousMode);
  53         }
  54     }
  55 
  56     /**
  57      * Constants denoting what type of collections are {@link CollectionsFactory#getMode()
  58      * currently} returned by the factory.
  59      */
  60     public enum Mode {
  61         /**
  62          * Denotes standard collections such as {@link HashSet} and {@link HashMap}.
  63          */
  64         STANDARD,
  65 
  66         /**
  67          * Denotes collections that have a deterministic iteration order over their keys/entries.
  68          */
  69         DETERMINISTIC_ITERATION_ORDER;
  70     }
  71 
  72     /**
  73      * Gets the current mode determining the type of collection objects created by this factory.
  74      */
  75     public static Mode getMode() {
  76         Mode mode = tl.get();
  77         return mode == null ? Mode.STANDARD : mode;
  78     }
  79 
  80     /**
  81      * Updates the mode for the current thread.
  82      *
  83      * @return an object which when {@linkplain ModeScope#close() closed} will revert the mode of
  84      *         the current thread to the state before calling this method
  85      */
  86     public static ModeScope changeMode(Mode mode) {
  87         Mode previousMode = tl.get();
  88         tl.set(mode);
  89         return new ModeScope(previousMode);
  90     }
  91 
  92     public static <K, V> HashMap<K, V> newMap() {
  93         return getMode() == STANDARD ? new HashMap<>() : new LinkedHashMap<>();
  94     }
  95 
  96     public static <K, V> HashMap<K, V> newMap(Map<K, V> m) {
  97         return getMode() == STANDARD ? new HashMap<>(m) : new LinkedHashMap<>(m);
  98     }
  99 
 100     public static <K, V> HashMap<K, V> newMap(int initialCapacity) {
 101         return getMode() == STANDARD ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity);
 102     }
 103 
 104     public static <K, V> Map<K, V> newIdentityMap() {
 105         return getMode() == STANDARD ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>();
 106     }
 107 
 108     public static <K, V> Map<K, V> newIdentityMap(int expectedMaxSize) {
 109         return getMode() == STANDARD ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>();
 110     }
 111 
 112     public static <K, V> Map<K, V> newIdentityMap(Map<K, V> m) {
 113         return getMode() == STANDARD ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m);
 114     }
 115 
 116     /**
 117      * Creates a set. If the current thread is {@linkplain CollectionsFactory#getMode() using}
 118      * {@link Mode#DETERMINISTIC_ITERATION_ORDER} collections, the returned set will have an
 119      * iteration order determined by the order in which elements are inserted in the set.
 120      */
 121     public static <E> Set<E> newSet() {
 122         return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>() : new LinkedHashSet<>();
 123     }
 124 
 125     /**
 126      * @see #newSet()
 127      */
 128     public static <E> Set<E> newSet(Collection<? extends E> c) {
 129         return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>(c) : new LinkedHashSet<>(c);
 130     }
 131 
 132 }