InMemoryStore.java

package net.morimekta.providence.storage;

import net.morimekta.util.concurrent.ReadWriteMutex;
import net.morimekta.util.concurrent.ReentrantReadWriteMutex;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * Simple in-memory storage of providence messages. Uses a local hash map for
 * storing the instances. The store is thread safe through using re-entrant
 * read-write mutex handling, so reading can happen in parallel.
 */
public class InMemoryStore<K, M> implements ReadWriteStore<K,M> {
    private final Map<K, M>      map;
    private final ReadWriteMutex mutex;

    public InMemoryStore() {
        map   = new HashMap<>();
        mutex = new ReentrantReadWriteMutex();
    }

    @Nonnull
    @Override
    public Map<K, M> getAll(@Nonnull Collection<K> keys) {
        return mutex.lockForReading(() -> {
            Map<K, M> out = new HashMap<>();
            for (K key : keys) {
                if (map.containsKey(key)) {
                    out.put(key, map.get(key));
                }
            }
            return out;
        });
    }

    @Override
    public boolean containsKey(@Nonnull K key) {
        return mutex.lockForReading(() -> map.containsKey(key));
    }

    @Override @Nonnull
    public Collection<K> keys() {
        return mutex.lockForReading(() -> new HashSet<>(map.keySet()));
    }

    @Override
    public int size() {
        return mutex.lockForReading(map::size);
    }

    @Override
    public void putAll(@Nonnull Map<K, M> values) {
        mutex.lockForWriting(() -> map.putAll(values));
    }

    @Override
    public void removeAll(Collection<K> keys) {
        mutex.lockForWriting(() -> map.keySet().removeAll(keys));
    }
}