001 package org.apache.commons.ognl.internal;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 /*
023 * $Id: ReentrantReadWriteLockCache.java 1194954 2011-10-29 18:00:27Z mcucchiara $
024 */
025
026 import org.apache.commons.ognl.internal.entry.CacheEntryFactory;
027
028 import java.util.HashMap;
029 import java.util.Map;
030 import java.util.concurrent.locks.Lock;
031 import java.util.concurrent.locks.ReadWriteLock;
032 import java.util.concurrent.locks.ReentrantReadWriteLock;
033
034 public class ReentrantReadWriteLockCache<K, V>
035 implements Cache<K, V>
036 {
037 private final ReadWriteLock lock = new ReentrantReadWriteLock();
038
039 private final Lock readLock = lock.readLock();
040
041 private final Lock writeLock = lock.writeLock();
042
043 final Map<K, V> cache = new HashMap<K, V>();
044
045 private CacheEntryFactory<K, V> cacheEntryFactory;
046
047 public ReentrantReadWriteLockCache()
048 {
049 }
050
051 public ReentrantReadWriteLockCache( CacheEntryFactory<K, V> cacheEntryFactory )
052 {
053 this.cacheEntryFactory = cacheEntryFactory;
054 }
055
056 public void clear()
057 {
058 synchronized ( cache )
059 {
060 cache.clear();
061 }
062 }
063
064 public int getSize()
065 {
066 synchronized ( cache )
067 {
068 return cache.size();
069 }
070 }
071
072
073 public V get( K key )
074 throws CacheException
075 {
076 V v;
077 boolean shouldCreate;
078 readLock.lock();
079 try
080 {
081 v = cache.get( key );
082 shouldCreate = shouldCreate( cacheEntryFactory, v );
083 }
084 finally
085 {
086 readLock.unlock();
087 }
088 if ( shouldCreate )
089 {
090 try
091 {
092 writeLock.lock();
093 v = cache.get( key );
094 if ( !shouldCreate( cacheEntryFactory, v ) )
095 {
096 return v;
097 }
098 v = cacheEntryFactory.create( key );
099 cache.put( key, v );
100 return v;
101 }
102 finally
103 {
104 writeLock.unlock();
105 }
106
107 }
108
109 return v;
110 }
111
112 protected boolean shouldCreate( CacheEntryFactory<K, V> cacheEntryFactory, V v )
113 throws CacheException
114 {
115 if ( cacheEntryFactory != null )
116 {
117 if ( v == null )
118 {
119 return true;
120 }
121 }
122 return false;
123 }
124
125 public V put( K key, V value )
126 {
127 writeLock.lock();
128 try
129 {
130 cache.put( key, value );
131 return value;
132 }
133 finally
134 {
135 writeLock.unlock();
136 }
137 }
138 }