/**
* Copyright 2011-2012 Akiban Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.persistit;
import com.persistit.exception.PersistitInterruptedException;
import com.persistit.util.Debug;
/**
* A container for a SharedResource that experiences reentrant claims (locks).
* {@link Exchange} uses this to hold a Tree object, which experiences this
* pattern. The purpose is to keep a count of so that when an Exchange has
* finished using the Tree, it can verify that all claims were released. This is
* primarily for debugging; correct code will always release each claim.
*/
class ReentrantResourceHolder {
private final SharedResource _resource;
private int _claimCount;
ReentrantResourceHolder(final SharedResource r) {
_resource = r;
}
void verifyReleased() {
Debug.$assert0.t(_claimCount == 0);
_claimCount = 0;
}
boolean claim(final boolean writer) throws PersistitInterruptedException {
return claim(writer, SharedResource.DEFAULT_MAX_WAIT_TIME);
}
boolean claim(final boolean writer, final long timeout) throws PersistitInterruptedException {
if (_claimCount == 0) {
if (!_resource.claim(writer, timeout)) {
return false;
} else {
_claimCount++;
return true;
}
} else {
if (writer && !_resource.isWriter()) {
if (!_resource.upgradeClaim()) {
return false;
}
}
_claimCount++;
return true;
}
}
void release() {
if (_claimCount <= 0) {
throw new IllegalStateException("This thread holds no claims");
}
if (--_claimCount == 0) {
_resource.release();
}
}
boolean upgradeClaim() {
return _resource.upgradeClaim();
}
}