Parcourir la source

new: Meta.ThreadSafe
new: MapUtils#synchronizedMultiMap

Mariusz Sieroń il y a 6 ans
Parent
commit
ad2795a886

+ 8 - 0
assira/src/main/java/net/ranides/assira/annotations/Meta.java

@@ -140,4 +140,12 @@ public final class Meta {
     public @interface Experimental {
     }
 
+
+    @Target({METHOD, TYPE})
+    @Retention(SOURCE)
+    @Documented
+    public @interface ThreadSafe {
+
+    }
+
 }

+ 388 - 5
assira/src/main/java/net/ranides/assira/collection/maps/MapUtils.java

@@ -9,10 +9,8 @@ package net.ranides.assira.collection.maps;
 import java.io.Serializable;
 import java.util.*;
 import java.util.AbstractMap.SimpleEntry;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
+import java.util.function.*;
+import java.util.stream.Stream;
 
 import net.ranides.assira.collection.ACollection;
 import net.ranides.assira.collection.CollectionUtils;
@@ -74,6 +72,10 @@ public final class MapUtils {
         return new ViewAdapter<>(map, keyMapper, valueMapper);
     }
 
+    public static <K, V> MultiMap<K, V> synchronizedMultiMap(MultiMap<K, V> map) {
+        return new SynchronizedMultiMap<K, V>(map);
+    }
+
     private static class ViewAdapter<TK, RK, TV, RV> extends AMap<RK, RV> {
 
         private final Map<TK,? extends TV> content;
@@ -681,5 +683,386 @@ public final class MapUtils {
         }
 
     }
-    
+
+    private static class SynchronizedMultiMap<K, V> implements MultiMap<K, V> {
+
+        private final Object mutex = new Object();
+
+        private final MultiMap<K, V> data;
+
+        private Set<K> keySet;
+        private Set<Map.Entry<K,V>> entrySet;
+        private Collection<V> values;
+
+        public SynchronizedMultiMap(MultiMap<K, V> data) {
+            this.data = data;
+        }
+
+        @Override
+        public Collection<V> getAll(Object key) {
+            synchronized (mutex) {
+                return new SynchronizedCollection<>(mutex, data.getAll(key));
+            }
+        }
+
+        @Override
+        public int size() {
+            synchronized (mutex) {
+                return data.size();
+            }
+        }
+
+        @Override
+        public boolean isEmpty() {
+            synchronized (mutex) {
+                return data.isEmpty();
+            }
+        }
+
+        @Override
+        public boolean containsKey(Object key) {
+            synchronized (mutex) {
+                return data.containsKey(key);
+            }
+        }
+
+        @Override
+        public boolean containsValue(Object value) {
+            synchronized (mutex) {
+                return data.containsValue(value);
+            }
+        }
+
+        @Override
+        public V get(Object key) {
+            synchronized (mutex) {
+                return data.get(key);
+            }
+        }
+
+        @Override
+        public V put(K key, V value) {
+            synchronized (mutex) {
+                return data.put(key, value);
+            }
+        }
+
+        @Override
+        public V remove(Object key) {
+            synchronized (mutex) {
+                return data.remove(key);
+            }
+        }
+
+        @Override
+        public void putAll(Map<? extends K, ? extends V> m) {
+            synchronized (mutex) {
+                data.putAll(m);
+            }
+        }
+
+        @Override
+        public void clear() {
+            synchronized (mutex) {
+                data.clear();
+            }
+        }
+
+        @Override
+        public Set<K> keySet() {
+            synchronized (mutex) {
+                if(keySet == null) {
+                    keySet = new SynchronizedSet<>(mutex, data.keySet());
+                }
+                return keySet;
+            }
+        }
+
+        @Override
+        public Collection<V> values() {
+            synchronized (mutex) {
+                if(values == null) {
+                    values = new SynchronizedCollection<>(mutex, data.values());
+                }
+                return values;
+            }
+        }
+
+        @Override
+        public Set<Entry<K, V>> entrySet() {
+            synchronized (mutex) {
+                if(entrySet == null) {
+                    entrySet = new SynchronizedSet<>(mutex, data.entrySet());
+                }
+                return entrySet;
+            }
+        }
+
+        @Override
+        public V get(Object key, BinaryOperator<V> fold) {
+            synchronized (mutex) {
+                return data.get(key, fold);
+            }
+        }
+
+        @Override
+        public boolean containsEntry(Object key, Object value) {
+            synchronized (mutex) {
+                return data.containsEntry(key, value);
+            }
+        }
+
+        @Override
+        public void putAll(K key, Iterable<? extends V> values) {
+            synchronized (mutex) {
+                data.putAll(key, values);
+            }
+        }
+
+        @Override
+        public V replace(K key, V value) {
+            synchronized (mutex) {
+                return data.replace(key, value);
+            }
+        }
+
+        @Override
+        public Collection<V> replaceAll(K key, Collection<V> values) {
+            synchronized (mutex) {
+                return data.replaceAll(key, values);
+            }
+        }
+
+        @Override
+        public boolean remove(Object key, Object value) {
+            synchronized (mutex) {
+                return data.remove(key, value);
+            }
+        }
+
+        @Override
+        public Collection<V> removeAll(Object key) {
+            synchronized (mutex) {
+                return data.removeAll(key);
+            }
+        }
+
+        @Override
+        public Set<K> uniqueKeySet() {
+            synchronized (mutex) {
+                return data.uniqueKeySet();
+            }
+        }
+
+        @Override
+        public V getOrDefault(Object key, V defaultValue) {
+            synchronized (mutex) {
+                return data.getOrDefault(key, defaultValue);
+            }
+        }
+
+        @Override
+        public void forEach(BiConsumer<? super K, ? super V> action) {
+            synchronized (mutex) {
+                data.forEach(action);
+            }
+        }
+
+        @Override
+        public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+            synchronized (mutex) {
+                data.replaceAll(function);
+            }
+        }
+
+        @Override
+        public V putIfAbsent(K key, V value) {
+            synchronized (mutex) {
+                return data.putIfAbsent(key, value);
+            }
+        }
+
+        @Override
+        public boolean replace(K key, V oldValue, V newValue) {
+            synchronized (mutex) {
+                return data.replace(key, oldValue, newValue);
+            }
+        }
+
+        @Override
+        public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+            synchronized (mutex) {
+                return data.computeIfAbsent(key, mappingFunction);
+            }
+        }
+
+        @Override
+        public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+            synchronized (mutex) {
+                return data.computeIfPresent(key, remappingFunction);
+            }
+        }
+
+        @Override
+        public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+            synchronized (mutex) {
+                return data.compute(key, remappingFunction);
+            }
+        }
+
+        @Override
+        public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+            synchronized (mutex) {
+                return data.merge(key, value, remappingFunction);
+            }
+        }
+
+    }
+
+    static class SynchronizedCollection<E> implements Collection<E> {
+
+        final Collection<E> c;
+
+        final Object mutex;
+
+        SynchronizedCollection(Object mutex, Collection<E> c) {
+            this.c = Objects.requireNonNull(c);
+            this.mutex = Objects.requireNonNull(mutex);
+        }
+
+        public int size() {
+            synchronized (mutex) {
+                return c.size();
+            }
+        }
+
+        public boolean isEmpty() {
+            synchronized (mutex) {
+                return c.isEmpty();
+            }
+        }
+
+        public boolean contains(Object o) {
+            synchronized (mutex) {
+                return c.contains(o);
+            }
+        }
+
+        public Object[] toArray() {
+            synchronized (mutex) {
+                return c.toArray();
+            }
+        }
+
+        public <T> T[] toArray(T[] a) {
+            synchronized (mutex) {
+                return c.toArray(a);
+            }
+        }
+
+        public Iterator<E> iterator() {
+            return c.iterator(); // Must be manually synched by user!
+        }
+
+        public boolean add(E e) {
+            synchronized (mutex) {
+                return c.add(e);
+            }
+        }
+
+        public boolean remove(Object o) {
+            synchronized (mutex) {
+                return c.remove(o);
+            }
+        }
+
+        public boolean containsAll(Collection<?> coll) {
+            synchronized (mutex) {
+                return c.containsAll(coll);
+            }
+        }
+
+        public boolean addAll(Collection<? extends E> coll) {
+            synchronized (mutex) {
+                return c.addAll(coll);
+            }
+        }
+
+        public boolean removeAll(Collection<?> coll) {
+            synchronized (mutex) {
+                return c.removeAll(coll);
+            }
+        }
+
+        public boolean retainAll(Collection<?> coll) {
+            synchronized (mutex) {
+                return c.retainAll(coll);
+            }
+        }
+
+        public void clear() {
+            synchronized (mutex) {
+                c.clear();
+            }
+        }
+
+        public String toString() {
+            synchronized (mutex) {
+                return c.toString();
+            }
+        }
+
+        @Override
+        public void forEach(Consumer<? super E> consumer) {
+            synchronized (mutex) {
+                c.forEach(consumer);
+            }
+        }
+
+        @Override
+        public boolean removeIf(Predicate<? super E> filter) {
+            synchronized (mutex) {
+                return c.removeIf(filter);
+            }
+        }
+
+        @Override
+        public Spliterator<E> spliterator() {
+            return c.spliterator(); // Must be manually synched by user!
+        }
+
+        @Override
+        public Stream<E> stream() {
+            return c.stream(); // Must be manually synched by user!
+        }
+
+        @Override
+        public Stream<E> parallelStream() {
+            return c.parallelStream(); // Must be manually synched by user!
+        }
+
+    }
+
+    static class SynchronizedSet<E> extends SynchronizedCollection<E> implements Set<E> {
+
+        SynchronizedSet(Object mutex, Set<E> s) {
+            super(mutex, s);
+        }
+
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            synchronized (mutex) {
+                return c.equals(o);
+            }
+        }
+
+        public int hashCode() {
+            synchronized (mutex) {
+                return c.hashCode();
+            }
+        }
+    }
+
 }