001: /*
002:
003: Derby - Class org.apache.derby.impl.services.locks.Lock
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: 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, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.services.locks;
023:
024: import org.apache.derby.iapi.services.locks.Lockable;
025: import org.apache.derby.iapi.services.locks.Latch;
026:
027: import org.apache.derby.iapi.services.sanity.SanityManager;
028:
029: import java.util.List;
030:
031: /**
032: A Lock represents a granted or waiting lock request.
033:
034: <BR>
035: MT - Mutable - Immutable identity : Thread Aware
036: */
037:
038: public class Lock implements Latch, Control {
039:
040: /**
041: Compatibility space the object is locked in.
042: MT - immutable - reference only
043: */
044: private final Object space;
045:
046: /**
047: Object being locked.
048: MT - immutable - reference only
049: */
050: private final Lockable ref;
051: /**
052: Qualifier used in the lock request..
053: MT - immutable - reference only
054: */
055: private final Object qualifier;
056:
057: int count;
058:
059: protected Lock(Object space, Lockable ref, Object qualifier) {
060: super ();
061: this .space = space;
062: this .ref = ref;
063: this .qualifier = qualifier;
064: }
065:
066: /**
067: Return the object this lock is held on
068:
069: MT - Thread safe
070: */
071: public final Lockable getLockable() {
072: return ref;
073: }
074:
075: /**
076: Return the compatability space this lock is held in
077:
078: MT - Thread safe
079: */
080: public final Object getCompatabilitySpace() {
081: return space;
082: }
083:
084: /**
085: Return the qualifier lock was obtained with.
086:
087: MT - Thread safe
088: */
089:
090: public final Object getQualifier() {
091: return qualifier;
092: }
093:
094: /**
095: Return the count of locks.
096:
097: MT - Thread safe
098: */
099:
100: public final int getCount() {
101: return count;
102: }
103:
104: // make a copy of this lock with the count set to zero, copies are only
105: // to be used in the LockSpace code.
106: final Lock copy() {
107:
108: return new Lock(space, ref, qualifier);
109: }
110:
111: void grant() {
112:
113: count++;
114:
115: // Tell the object it has been locked by this type of qualifier.
116: ref.lockEvent(this );
117: }
118:
119: int unlock(int unlockCount) {
120:
121: if (unlockCount > count)
122: unlockCount = count;
123:
124: count -= unlockCount;
125: if (count == 0) {
126:
127: // Inform the object an unlock event occured with this qualifier
128:
129: ref.unlockEvent(this );
130: }
131:
132: return unlockCount;
133: }
134:
135: /*
136: ** Methods of object
137: */
138:
139: public final int hashCode() {
140:
141: // qualifier can be null so don't use it in hashCode
142:
143: return ref.hashCode() ^ space.hashCode();
144: }
145:
146: public final boolean equals(Object other) {
147:
148: if (other instanceof Lock) {
149: Lock ol = (Lock) other;
150:
151: return (space.equals(ol.space)) && ref.equals(ol.ref)
152: && (qualifier == ol.qualifier);
153: }
154:
155: return false;
156: }
157:
158: /*
159: ** Methods of Control
160: */
161:
162: public LockControl getLockControl() {
163: return new LockControl(this , ref);
164: }
165:
166: public Lock getLock(Object compatabilitySpace, Object qualifier) {
167: if (space.equals(compatabilitySpace)
168: && (this .qualifier == qualifier))
169: return this ;
170: return null;
171: }
172:
173: //EXCLUDE-START-lockdiag-
174: /**
175: We can return ourselves here because our identity
176: is immutable and what we returned will not be accessed
177: as a Lock, so the count cannot be changed.
178: */
179: public Control shallowClone() {
180: return this ;
181: }
182:
183: //EXCLUDE-END-lockdiag-
184:
185: public ActiveLock firstWaiter() {
186: return null;
187: }
188:
189: public boolean isEmpty() {
190: return count == 0;
191: }
192:
193: public boolean unlock(Latch lockInGroup, int unlockCount) {
194:
195: if (unlockCount == 0)
196: unlockCount = lockInGroup.getCount();
197:
198: if (SanityManager.DEBUG) {
199: if (unlockCount > getCount())
200: SanityManager.THROWASSERT(this + " unlockCount "
201: + unlockCount + " is greater than lockCount "
202: + getCount());
203: if (!equals(lockInGroup))
204: SanityManager.THROWASSERT(this + " mismatched locks "
205: + lockInGroup);
206:
207: }
208:
209: unlock(unlockCount);
210:
211: return false;
212: }
213:
214: public void addWaiters(java.util.Dictionary waiters) {
215: }
216:
217: public Lock getFirstGrant() {
218: return this ;
219: }
220:
221: public List getGranted() {
222: return null;
223: }
224:
225: public List getWaiting() {
226: return null;
227: }
228:
229: public boolean isGrantable(boolean noWaitersBeforeMe,
230: Object compatabilitySpace, Object requestQualifier) {
231: boolean sameSpace = space.equals(compatabilitySpace);
232: if (sameSpace && ref.lockerAlwaysCompatible())
233: return true;
234:
235: return ref.requestCompatible(requestQualifier, this.qualifier);
236: }
237: }
|