All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.objectfabric.WeakCache Maven / Gradle / Ivy

There is a newer version: 0.9.1
Show newest version
/**
 * This file is part of ObjectFabric (http://objectfabric.org).
 *
 * ObjectFabric is licensed under the Apache License, Version 2.0, the terms
 * of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
 * 
 * Copyright ObjectFabric Inc.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package org.objectfabric;

import java.util.Iterator;

@SuppressWarnings({ "unchecked", "rawtypes" })
abstract class WeakCache {

    private final PlatformConcurrentMap _map = new PlatformConcurrentMap();

    abstract V create(K key);

    abstract void onAdded(PlatformRef ref);

    final V get(K key) {
        for (;;) {
            Ref current = _map.get(key);

            if (current == null)
                return null;

            V value = (V) current.get();

            if (value != null)
                return value;
        }
    }

    final V getOrCreate(K key) {
        V created = null;

        for (;;) {
            Ref current = _map.get(key);

            if (current != null) {
                V value = (V) current.get();

                if (value != null)
                    return value;
            }

            if (created == null) {
                created = create(key);

                if (Debug.ENABLED)
                    Debug.assertion(created != null);
            }

            V value = created;
            Ref update = new Ref(key, value, _map);

            if (current != null && _map.replace(key, current, update)) {
                onAdded(update);
                return value;
            }

            current = _map.putIfAbsent(key, update);

            if (current != null)
                value = (V) current.get();
            else
                onAdded(update);

            if (value != null)
                return value;
        }
    }

    final void remove(K key) {
        Ref ref = _map.remove(key);

        if (ref != null)
            ref.clear();
    }

    final Iterable values() {
        return new Iterable() {

            @Override
            public Iterator iterator() {
                return new It(_map.values().iterator());
            }
        };
    }

    private static class It implements Iterator {

        private Iterator _values;

        private T _next;

        It(Iterator values) {
            _values = values;
        }

        @Override
        public boolean hasNext() {
            while (_values.hasNext()) {
                Ref ref = (Ref) _values.next();
                _next = (T) ref.get();

                if (_next != null)
                    return true;
            }

            return false;
        }

        @Override
        public T next() {
            return _next;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    private static final class Ref extends PlatformRef {

        private final Object _key;

        private final PlatformConcurrentMap _map;

        Ref(Object key, Object value, PlatformConcurrentMap map) {
            super(value, Platform.get().getReferenceQueue());

            _key = key;
            _map = map;
        }

        @Override
        void collected() {
            _map.remove(_key, this);
        }
    }

    // Testing

    final int getInternalMapSize() {
        return _map.size();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy