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

ratpack.registry.internal.HierarchicalRegistryCaching Maven / Gradle / Ivy

There is a newer version: 2.0.0-rc-1
Show newest version
/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ratpack.registry.internal;

import ratpack.registry.Registry;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class HierarchicalRegistryCaching {

  private static final ReferenceQueue REFERENCE_QUEUE = new ReferenceQueue<>();

  private static class CacheKey {
    final WeakReference parent;
    final WeakReference child;
    final int parentHashCode;
    final int childHashCode;

    public CacheKey(WeakReference parent, WeakReference child) {
      this.parent = parent;
      this.child = child;
      this.parentHashCode = System.identityHashCode(parent.get());
      this.childHashCode = System.identityHashCode(child.get());
    }

    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
    @Override
    public boolean equals(Object o) {
      Registry parentRegistry = parent.get();
      if (parentRegistry == null) {
        return false;
      }

      Registry childRegistry = child.get();
      if (childRegistry == null) {
        return false;
      }

      CacheKey other = (CacheKey) o;

      return parentRegistry.equals(other.parent.get()) && childRegistry.equals(other.child.get());
    }

    @Override
    public int hashCode() {
      return 31 * parentHashCode + childHashCode;
    }
  }

  private static final ConcurrentMap CACHE = new ConcurrentHashMap<>();

  public static Registry join(Registry parent, Registry child) {
    CacheKey cacheKey = new CacheKey(new WeakReference<>(parent, REFERENCE_QUEUE), new WeakReference<>(child, REFERENCE_QUEUE));
    Registry registry = CACHE.computeIfAbsent(cacheKey, k ->
      CachingRegistry.of(new HierarchicalRegistry(parent, child))
    );

    Reference collected = REFERENCE_QUEUE.poll();
    while (collected != null) {
      Iterator iterator = CACHE.keySet().iterator();
      while (iterator.hasNext()) {
        CacheKey k = iterator.next();
        if (k.parent == collected || k.child == collected) {
          iterator.remove();
        }
      }
      collected = REFERENCE_QUEUE.poll();
    }

    return registry;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy