
org.jboss.logmanager.CopyOnWriteWeakMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jboss-logmanager Show documentation
Show all versions of jboss-logmanager Show documentation
An implementation of java.util.logging.LogManager
The newest version!
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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 org.jboss.logmanager;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
final class CopyOnWriteWeakMap extends AbstractMap implements ConcurrentMap {
private final Queue queue = new Queue();
private static final FastCopyHashMap EMPTY = new FastCopyHashMap(32, 0.25f);
@SuppressWarnings({ "unchecked" })
private FastCopyHashMap> empty() {
return (FastCopyHashMap>) EMPTY;
}
private volatile FastCopyHashMap> map = empty();
private FastCopyHashMap> cleanCopyForRemove() {
assert Thread.holdsLock(this);
final Map> oldMap = map;
final Queue queue = this.queue;
if (oldMap.isEmpty()) {
queue.clear();
return empty();
}
final FastCopyHashMap> newMap = new FastCopyHashMap>(oldMap);
Node ref;
while ((ref = queue.poll()) != null) {
final Object key = ref.getKey();
if (newMap.get(key) == ref) {
newMap.remove(key);
if (newMap.isEmpty()) {
queue.clear();
return empty();
}
}
}
return newMap;
}
private FastCopyHashMap> cleanCopyForMod() {
assert Thread.holdsLock(this);
final Map> oldMap = map;
final Queue queue = this.queue;
if (oldMap.isEmpty()) {
queue.clear();
return empty().clone();
}
final FastCopyHashMap> newMap = new FastCopyHashMap>(oldMap);
Node ref;
while ((ref = queue.poll()) != null) {
final Object key = ref.getKey();
if (newMap.get(key) == ref) {
newMap.remove(key);
if (newMap.isEmpty()) {
queue.clear();
return empty().clone();
}
}
}
return newMap;
}
public V putIfAbsent(final K key, final V value) {
if (key == null) {
throw new IllegalArgumentException("key is null");
}
if (value == null) {
throw new IllegalArgumentException("value is null");
}
synchronized (this) {
final Node oldNode = map.get(key);
if (oldNode != null) {
final V val = oldNode.get();
if (val != null)
return val;
}
final FastCopyHashMap> newMap = cleanCopyForMod();
newMap.put(key, new Node(key, value, queue));
map = newMap;
return null;
}
}
public boolean remove(final Object key, final Object value) {
synchronized (this) {
final Node oldNode = map.get(key);
final V existing = oldNode.get();
if (existing != null && existing.equals(value)) {
final FastCopyHashMap> newMap = cleanCopyForRemove();
newMap.remove(key);
map = newMap;
return true;
}
}
return false;
}
public boolean replace(final K key, final V oldValue, final V newValue) {
if (newValue == null) {
throw new IllegalArgumentException("newValue is null");
}
if (oldValue == null) {
return false;
}
synchronized (this) {
final Node oldNode = map.get(key);
final V existing = oldNode.get();
if (existing != null && existing.equals(oldValue)) {
final FastCopyHashMap> newMap = cleanCopyForMod();
map.put(key, new Node(key, newValue, queue));
map = newMap;
return true;
}
}
return false;
}
public V replace(final K key, final V value) {
if (value == null) {
throw new IllegalArgumentException("value is null");
}
synchronized (this) {
final Node oldNode = map.get(key);
final V existing = oldNode.get();
if (existing != null) {
final FastCopyHashMap> newMap = cleanCopyForMod();
map.put(key, new Node(key, value, queue));
map = newMap;
}
return existing;
}
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean containsKey(final Object key) {
return map.containsKey(key);
}
public boolean containsValue(final Object value) {
if (value == null)
return false;
for (Node node : map.values()) {
if (value.equals(node.get())) {
return true;
}
}
return false;
}
public V get(final Object key) {
final Node node = map.get(key);
return node == null ? null : node.get();
}
public V put(final K key, final V value) {
if (key == null) {
throw new IllegalArgumentException("key is null");
}
if (value == null) {
throw new IllegalArgumentException("value is null");
}
synchronized (this) {
final FastCopyHashMap> newMap = cleanCopyForMod();
final Node old = newMap.put(key, new Node(key, value, queue));
map = newMap;
return old == null ? null : old.get();
}
}
public V remove(final Object key) {
if (key == null)
return null;
synchronized (this) {
final FastCopyHashMap> newMap = cleanCopyForRemove();
final Node old = newMap.remove(key);
map = newMap;
return old == null ? null : old.get();
}
}
public void clear() {
synchronized (this) {
map = empty();
}
}
public Set> entrySet() {
final FastCopyHashMap> snapshot = map;
final Map copyMap = new HashMap();
for (Node node : snapshot.values()) {
final V value = node.get();
if (value == null)
continue;
final K key = node.getKey();
copyMap.put(key, value);
}
return Collections.unmodifiableMap(copyMap).entrySet();
}
private static final class Node extends WeakReference {
private final K key;
Node(final K key, final V value, final ReferenceQueue super V> queue) {
super(value, queue);
this.key = key;
}
K getKey() {
return key;
}
}
private static final class Queue extends ReferenceQueue {
public Node poll() {
return (Node) super.poll();
}
void clear() {
while (poll() != null)
;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy