001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.kernel.concurrent;
016    
017    import com.liferay.portal.kernel.util.StringBundler;
018    import com.liferay.portal.kernel.util.Validator;
019    
020    import java.util.concurrent.atomic.AtomicMarkableReference;
021    
022    /**
023     * @author Shuyang Zhou
024     */
025    public abstract class IncreasableEntry<K, V> {
026    
027            public IncreasableEntry(K key, V value) {
028                    _key = key;
029                    _markedValue = new AtomicMarkableReference<V>(value, false);
030            }
031    
032            public abstract V doIncrease(V originalValue, V deltaValue);
033    
034            public boolean equals(Object obj) {
035                    if (this == obj) {
036                            return true;
037                    }
038    
039                    if (!(obj instanceof IncreasableEntry<?, ?>)) {
040                            return false;
041                    }
042    
043                    IncreasableEntry<K, V> increasableEntry = (IncreasableEntry<K, V>)obj;
044    
045                    if (Validator.equals(_key, increasableEntry._key) &&
046                            Validator.equals(
047                                    _markedValue.getReference(),
048                                    increasableEntry._markedValue.getReference())) {
049    
050                            return true;
051                    }
052    
053                    return false;
054            }
055    
056            public final K getKey() {
057                    return _key;
058            }
059    
060            public final V getValue() {
061                    while (true) {
062                            V value = _markedValue.getReference();
063    
064                            if (_markedValue.attemptMark(value, true)) {
065                                    return value;
066                            }
067                    }
068            }
069    
070            public int hashCode() {
071                    int hash = 77;
072    
073                    if (_key != null) {
074                            hash += _key.hashCode();
075                    }
076    
077                    hash = 11 * hash;
078    
079                    V value = _markedValue.getReference();
080    
081                    if (value != null) {
082                            hash += value.hashCode();
083                    }
084    
085                    return hash;
086            }
087    
088            public final boolean increase(V deltaValue) {
089                    boolean[] marked = {false};
090    
091                    while (true) {
092                            V originalValue = _markedValue.get(marked);
093    
094                            if (marked[0]) {
095                                    return false;
096                            }
097                            else {
098                                    V newValue = doIncrease(originalValue, deltaValue);
099    
100                                    if (_markedValue.compareAndSet(
101                                                    originalValue, newValue, false, false)) {
102    
103                                            return true;
104                                    }
105                            }
106                    }
107            }
108    
109            public String toString() {
110                    StringBundler sb = new StringBundler(5);
111    
112                    sb.append("{key=");
113                    sb.append(String.valueOf(_key.toString()));
114                    sb.append(", value=");
115                    sb.append(String.valueOf(_markedValue.getReference()));
116                    sb.append("}");
117    
118                    return sb.toString();
119            }
120    
121            private final K _key;
122            private final AtomicMarkableReference<V> _markedValue;
123    
124    }