summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSRecursiveLock.java
blob: 999af6c71dc9c906b12c8e0a5d71839955f948a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
Wotonomy: OpenStep design patterns for pure Java applications.
Copyright (C) 2002 Israfil consulting Services Corporation

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see http://www.gnu.org

$Id: NSRecursiveLock.java 893 2006-02-16 13:22:23Z cgruber $

*/

package net.wotonomy.foundation;

import EDU.oswego.cs.dl.util.concurrent.ReentrantLock;

/**
 * A lock class that allows a thread to re-acquire it's lock recursively.
 * Currently an API-compliance wrapper around Doug Lea's ReentrantLock,
 * conforming to the API and behavior of
 * com.webobjects.foundation.NSRecursiveLock.
 *
 * @author cgruber@israfil.net
 * @author $Author: cgruber $
 * @version $Revision: 893 $
 */

public class NSRecursiveLock extends ReentrantLock implements NSLocking {

	public NSRecursiveLock() {
	}

	/**
	 * Acquire the lock, catching the thrown exception to mirror the behavior of
	 * com.webobjects.foundation.NSRecursiveLock. Note that ReentrantLock.acquire()
	 * performs a notify() when it's interrupted.
	 * 
	 * @see edu.oswego.cs.dl.util.concurrent.ReentrantLock#acquire()
	 */
	public void lock() {
		try {
			acquire();
		} catch (InterruptedException interruptedexception) {
			// Null behavior, as notify() is already called
			// by acquire();
			// We may want to log here.
		}
	}

	/**
	 * Pass the buck to tryLock(long), passing zero time as the parameter.
	 * 
	 * @see #tryLock(long)
	 */
	public boolean tryLock() {
		return tryLock(1);
	}

	/**
	 * Attempt to acquire the lock, catching the thrown exception to mirror the
	 * behavior of com.webobjects.foundation.NSRecursiveLock. Note that
	 * ReentrantLock.attempt(*) performs a notify() when it's interrupted. Fail
	 * gracefully after the given milliseconds
	 * 
	 * @param (long)
	 * @see edu.oswego.cs.dl.util.concurrent.ReentrantLock#acquire()
	 */
	public boolean tryLock(long milliseconds) {
		try {
			return attempt(milliseconds);
		} catch (InterruptedException interruptedexception) {
			// notify() is already called by attempt();
			// We may want to log here.
			return false;
		}
	}

	/**
	 * Attempt to acquire a lock until the timestamp is reached. Add 1 to the
	 * recursion count if the calling thread already owns the lock. Otherwise block
	 * until free or until the given timestamp is reached.
	 * 
	 * @see Timestamp
	 * @see ReentrantLock.attempt(long);
	 */
	public boolean tryLock(NSTimestamp nstimestamp) {
		return tryLock(nstimestamp.getTime() - System.currentTimeMillis());
	}

	/**
	 * Unlock the current lock precisely once.
	 */
	public synchronized void unlock() {
		unlock(1);
	}

	/**
	 * Unlock the current lock count times.
	 */
	public synchronized void unlock(long count) {
		if (owner_ != null && Thread.currentThread() != owner_)
			throw new IllegalStateException("Illegal Lock usage: unlocking thread not owner.");
		if (owner_ == null || holds_ == 0L)
			throw new IllegalStateException("Illegal Lock usage: unlock() called without a lock().");
		release(count);
	}

	public synchronized long recursionCount() {
		return holds();
	}

	public String toString() {
		long holds = holds();
		boolean oneHold = (holds == 1);
		boolean noHolds = (holds < 1 || owner_ == null);
		return getClass().getName() + " <"
				+ ((noHolds) ? "Unlocked" : ("Locked " + holds + " time" + (oneHold ? "" : "s") + " by " + owner_))
				+ ">";
	}

}
/*
 * $Log$ Revision 1.2 2006/02/16 13:15:00 cgruber Check in all sources in
 * eclipse-friendly maven-enabled packages.
 *
 * Revision 1.1 2002/07/14 21:56:16 mpowers Contributions from cgruber.
 *
 * Revision 1.5 2002/06/25 19:02:19 cgruber I'm a dumbass.
 *
 * Revision 1.4 2002/06/25 18:52:56 cgruber Fix javadocs that resulted from bad
 * cut-and-paste of the boilerplate.
 *
 * Revision 1.3 2002/06/25 18:45:27 cgruber Add some javadocs.
 *
 * Revision 1.2 2002/06/25 18:06:48 cgruber Add implementation of
 * NSRecursiveLock using Doug Lea's concurrent programming APIs. Specifically
 * inherit from ReentrantLock, which magically does the exact job we want!
 *
 * Revision 1.1 2002/06/25 07:52:56 cgruber Add quite a few abstract classes,
 * interfaces, and classes. All API consistent with WebObjects, but with no
 * implementation, nor any private or package access members from the original.
 *
 */