EMMA Coverage Report (generated Tue Apr 17 08:51:20 BST 2007)
[all classes][org.jtoolkit.essence.utils]

COVERAGE SUMMARY FOR SOURCE FILE [RWLock.java]

nameclass, %method, %block, %line, %
RWLock.java100% (4/4)61%  (23/38)43%  (191/447)44%  (39.4/90)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RWLock$WriteLock100% (1/1)27%  (3/11)16%  (32/198)10%  (4/39)
addWriteLock (): void 0%   (0/1)0%   (0/14)0%   (0/3)
lock (): void 0%   (0/1)0%   (0/10)0%   (0/4)
lockInterruptibly (): void 0%   (0/1)0%   (0/41)0%   (0/5)
newCondition (): Condition 0%   (0/1)0%   (0/6)0%   (0/1)
removeWriteLock (): void 0%   (0/1)0%   (0/28)0%   (0/5)
tryLock (): boolean 0%   (0/1)0%   (0/14)0%   (0/5)
tryLock (long, TimeUnit): boolean 0%   (0/1)0%   (0/16)0%   (0/5)
unlock (): void 0%   (0/1)0%   (0/36)0%   (0/6)
checkReadLock (): void 100% (1/1)96%  (22/23)75%  (3/4)
RWLock$WriteLock (RWLock): void 100% (1/1)100% (6/6)100% (1/1)
RWLock$WriteLock (RWLock, RWLock$1): void 100% (1/1)100% (4/4)100% (1/1)
     
class RWLock100% (1/1)80%  (12/15)63%  (84/134)84%  (18.4/22)
access$700 (): Log 0%   (0/1)0%   (0/2)0%   (0/1)
getName (): String 0%   (0/1)0%   (0/3)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/20)0%   (0/1)
checkUnlocked (String): void 100% (1/1)29%  (8/28)75%  (3/4)
createLock (String): ReadWriteLock 100% (1/1)55%  (6/11)54%  (0.5/1)
<static initializer> 100% (1/1)100% (11/11)100% (3/3)
RWLock (String): void 100% (1/1)100% (37/37)100% (8/8)
access$200 (RWLock): ReentrantReadWriteLock 100% (1/1)100% (3/3)100% (1/1)
access$300 (RWLock): List 100% (1/1)100% (3/3)100% (1/1)
access$400 (): ThreadLocal 100% (1/1)100% (2/2)100% (1/1)
access$500 (RWLock): List 100% (1/1)100% (3/3)100% (1/1)
access$600 (RWLock): String 100% (1/1)100% (3/3)100% (1/1)
isDebug (): boolean 100% (1/1)100% (2/2)100% (1/1)
readLock (): Lock 100% (1/1)100% (3/3)100% (1/1)
writeLock (): Lock 100% (1/1)100% (3/3)100% (1/1)
     
class RWLock$ReadLock100% (1/1)60%  (6/10)63%  (68/108)56%  (15/27)
lockInterruptibly (): void 0%   (0/1)0%   (0/8)0%   (0/3)
newCondition (): Condition 0%   (0/1)0%   (0/6)0%   (0/1)
tryLock (): boolean 0%   (0/1)0%   (0/12)0%   (0/4)
tryLock (long, TimeUnit): boolean 0%   (0/1)0%   (0/14)0%   (0/4)
RWLock$ReadLock (RWLock): void 100% (1/1)100% (6/6)100% (1/1)
RWLock$ReadLock (RWLock, RWLock$1): void 100% (1/1)100% (4/4)100% (1/1)
addReadLock (): void 100% (1/1)100% (14/14)100% (3/3)
lock (): void 100% (1/1)100% (8/8)100% (3/3)
removeReadLock (): void 100% (1/1)100% (28/28)100% (5/5)
unlock (): void 100% (1/1)100% (8/8)100% (3/3)
     
class RWLock$1100% (1/1)100% (2/2)100% (7/7)100% (2/2)
RWLock$1 (): void 100% (1/1)100% (3/3)100% (1/1)
initialValue (): Set 100% (1/1)100% (4/4)100% (1/1)

1package org.jtoolkit.essence.utils;
2/*
3   Copyright 2006 Peter Lawrey
4 
5   Licensed under the Apache License, Version 2.0 (the "License");
6   you may not use this file except in compliance with the License.
7   You may obtain a copy of the License at
8 
9       http://www.apache.org/licenses/LICENSE-2.0
10 
11   Unless required by applicable law or agreed to in writing, software
12   distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
13   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   See the License for the specific language governing permissions and
15   limitations under the License.
16*/
17 
18import org.apache.commons.logging.Log;
19import org.apache.commons.logging.LogFactory;
20import org.jetbrains.annotations.NotNull;
21import org.jtoolkit.essence.ConfigProperties;
22 
23import java.util.*;
24import java.util.concurrent.TimeUnit;
25import java.util.concurrent.locks.Condition;
26import java.util.concurrent.locks.Lock;
27import java.util.concurrent.locks.ReadWriteLock;
28import java.util.concurrent.locks.ReentrantReadWriteLock;
29 
30/**
31 * A lock which can help you detect ReadWriteLock deadlocks and attempts to upgrade a lock.
32 * It will log which threads have locked a lock if you are waiting for one too long.
33 * It can also be used to ensure you have no locks when attempting a lengthy (blocking) operation.
34 * Use RWLock.createLock() to create a normal lock or one of these reporting locks based on a system property
35 * Add -Drwlock.debug=true to the commandline to turn on.
36 */
37public class RWLock implements ReadWriteLock, Named {
38    private static final Log LOG = LogFactory.getLog(RWLock.class);
39    private static final ThreadLocal<Set<RWLock>> thisThreadsLocks = new ThreadLocal<Set<RWLock>>() {
40        protected Set<RWLock> initialValue() {
41            return new LinkedHashSet<RWLock>();
42        }
43    };
44    private static final boolean DEBUG = Boolean.getBoolean(ConfigProperties.ESSENCE_RWLOCK_DEBUG);
45 
46    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
47    private final List<Thread> readThreads = Collections.synchronizedList(new ArrayList<Thread>());
48    private final List<Thread> writeThreads = Collections.synchronizedList(new ArrayList<Thread>());
49    private final String name;
50 
51    public RWLock(String name) {
52        this.name = name;
53    }
54 
55    @NotNull
56    public String getName() {
57        return name;
58    }
59 
60    private final Lock readLock = new ReadLock();
61 
62    private final Lock writeLock = new WriteLock();
63 
64    public static boolean isDebug() {
65        return DEBUG;
66    }
67 
68    public Lock readLock() {
69        return readLock;
70    }
71 
72    public Lock writeLock() {
73        return writeLock;
74    }
75 
76    public String toString() {
77        return "RWLock " + name + ",readThreads=" + readThreads + ",writeThreads=" + writeThreads;
78    }
79 
80    public static void checkUnlocked(String oper) {
81        Set<RWLock> rwLocks = thisThreadsLocks.get();
82        if (!rwLocks.isEmpty())
83            LOG.warn(Thread.currentThread() + ": Attempting " + oper + " while locked " + rwLocks, new Throwable("here"));
84    }
85 
86    public static ReadWriteLock createLock(String name) {
87        return DEBUG ? new RWLock(name) : new ReentrantReadWriteLock();
88    }
89 
90    private class ReadLock implements Lock {
91        public void lock() {
92            lock.readLock().lock();
93            addReadLock();
94        }
95 
96        public void lockInterruptibly() throws InterruptedException {
97            lock.readLock().lockInterruptibly();
98            addReadLock();
99        }
100 
101        public boolean tryLock() {
102            boolean ret = lock.readLock().tryLock();
103            if (ret)
104                addReadLock();
105            return ret;
106        }
107 
108        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
109            boolean ret = lock.readLock().tryLock(time, unit);
110            if (ret)
111                addReadLock();
112            return ret;
113        }
114 
115        public void unlock() {
116            lock.readLock().unlock();
117            removeReadLock();
118        }
119 
120        public Condition newCondition() {
121            return lock.readLock().newCondition();
122        }
123 
124        private void addReadLock() {
125            if (readThreads.add(Thread.currentThread()))
126                thisThreadsLocks.get().add(RWLock.this);
127        }
128 
129        private void removeReadLock() {
130            Thread t = Thread.currentThread();
131            readThreads.remove(t);
132            if (!readThreads.contains(t) && !writeThreads.contains(t))
133                thisThreadsLocks.get().remove(RWLock.this);
134        }
135    }
136 
137    private class WriteLock implements Lock {
138        public void lock() {
139            checkReadLock();
140            lock.writeLock().lock();
141            addWriteLock();
142        }
143 
144        public void lockInterruptibly() throws InterruptedException {
145            checkReadLock();
146            while (!lock.writeLock().tryLock(1000, TimeUnit.MILLISECONDS))
147                LOG.info(name + ": Unable to get lock for " + Thread.currentThread().getName() + " locked by read" + readThreads + ", write" + writeThreads);
148            addWriteLock();
149        }
150 
151        public boolean tryLock() {
152            checkReadLock();
153            boolean ret = lock.writeLock().tryLock();
154            if (ret)
155                addWriteLock();
156            return ret;
157        }
158 
159        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
160            checkReadLock();
161            boolean ret = lock.writeLock().tryLock(time, unit);
162            if (ret)
163                addWriteLock();
164            return ret;
165        }
166 
167        @SuppressWarnings({"ProhibitedExceptionCaught"})
168        public void unlock() {
169            try {
170                lock.writeLock().unlock();
171            } catch (IllegalMonitorStateException e) {
172                throw new IllegalMonitorStateException(name + ": Unable to unlock for " + Thread.currentThread() + " writeThreads" + writeThreads + ' ' + e);
173            }
174            removeWriteLock();
175        }
176 
177        public Condition newCondition() {
178            return lock.writeLock().newCondition();
179        }
180 
181        private void checkReadLock() {
182            Thread t = Thread.currentThread();
183            if (readThreads.contains(t))
184                throw new IllegalMonitorStateException(name + ": Cannot be upgraded from readLock to writeLock");
185        }
186 
187        private void addWriteLock() {
188            if (writeThreads.add(Thread.currentThread()))
189                thisThreadsLocks.get().add(RWLock.this);
190        }
191 
192        private void removeWriteLock() {
193            Thread t = Thread.currentThread();
194            writeThreads.remove(t);
195            if (!readThreads.contains(t) && !writeThreads.contains(t))
196                thisThreadsLocks.get().remove(RWLock.this);
197        }
198    }
199}

[all classes][org.jtoolkit.essence.utils]
EMMA 2.0.5312 (C) Vladimir Roubtsov